Chromium Code Reviews| Index: media/filters/audio_file_reader.cc |
| diff --git a/media/filters/audio_file_reader.cc b/media/filters/audio_file_reader.cc |
| index a3bb92e1dce829b302f9c49e2036d99b8587fc05..3c9ce58cdeeca310b4442598d24ba160a05103dc 100644 |
| --- a/media/filters/audio_file_reader.cc |
| +++ b/media/filters/audio_file_reader.cc |
| @@ -17,7 +17,8 @@ namespace media { |
| AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) |
| : protocol_(protocol), |
| format_context_(NULL), |
| - codec_context_(NULL) { |
| + codec_context_(NULL), |
| + stream_index_(0) { |
| } |
| AudioFileReader::~AudioFileReader() { |
| @@ -71,6 +72,7 @@ bool AudioFileReader::Open() { |
| AVCodecContext* c = format_context_->streams[i]->codec; |
| if (c->codec_type == AVMEDIA_TYPE_AUDIO) { |
| codec_context_ = c; |
| + stream_index_ = i; |
| break; |
| } |
| } |
| @@ -124,42 +126,62 @@ bool AudioFileReader::Read(AudioBus* audio_bus) { |
| // Read until we hit EOF or we've read the requested number of frames. |
| AVPacket packet; |
| - int result = 0; |
| int current_frame = 0; |
| - |
| - while (current_frame < audio_bus->frames() && |
| - (result = av_read_frame(format_context_, &packet)) >= 0) { |
| - avcodec_get_frame_defaults(av_frame.get()); |
| - int frame_decoded = 0; |
| - int result = avcodec_decode_audio4( |
| - codec_context_, av_frame.get(), &frame_decoded, &packet); |
| - av_free_packet(&packet); |
| - |
| - if (result < 0) { |
| - DLOG(WARNING) |
| - << "AudioFileReader::Read() : error in avcodec_decode_audio3() -" |
| - << result; |
| - break; |
| - } |
| - |
| - if (!frame_decoded) |
| + bool continue_decoding = true; |
| + |
| + while (current_frame < audio_bus->frames() && continue_decoding && |
| + av_read_frame(format_context_, &packet) >= 0 && |
| + av_dup_packet(&packet) >= 0) { |
| + // Skip packets from other streams. |
|
DaleCurtis
2012/08/28 20:19:17
Noticed this while testing, previously handing a c
|
| + if (packet.stream_index != stream_index_) { |
| + av_free_packet(&packet); |
| continue; |
| + } |
| - // Determine the number of sample-frames we just decoded. Check overflow. |
| - int frames_read = av_frame->nb_samples; |
| - if (frames_read < 0) |
| - break; |
| - |
| - // Truncate, if necessary, if the destination isn't big enough. |
| - if (current_frame + frames_read > audio_bus->frames()) |
| - frames_read = audio_bus->frames() - current_frame; |
| - |
| - // Deinterleave each channel and convert to 32bit floating-point |
| - // with nominal range -1.0 -> +1.0. |
| - audio_bus->FromInterleavedPartial( |
| - av_frame->data[0], current_frame, frames_read, bytes_per_sample); |
| - |
| - current_frame += frames_read; |
| + // Make a shallow copy of packet so we can slide packet.data as frames are |
| + // decoded from the packet; otherwise av_free_packet() will corrupt memory. |
| + AVPacket packet_temp = packet; |
| + do { |
| + avcodec_get_frame_defaults(av_frame.get()); |
| + int frame_decoded = 0; |
| + int result = avcodec_decode_audio4( |
| + codec_context_, av_frame.get(), &frame_decoded, &packet_temp); |
| + |
| + if (result < 0) { |
| + DLOG(WARNING) |
| + << "AudioFileReader::Read() : error in avcodec_decode_audio4() -" |
| + << result; |
| + continue_decoding = false; |
| + break; |
| + } |
| + |
| + // Update packet size and data pointer in case we need to call the decoder |
| + // with the remaining bytes from this packet. |
| + packet_temp.size -= result; |
| + packet_temp.data += result; |
| + |
| + if (!frame_decoded) |
|
acolwell GONE FROM CHROMIUM
2012/08/28 20:31:53
Does there need to be a if (packet_temp.size == 0)
DaleCurtis
2012/08/28 21:41:17
I'm not sure I follow; this continue affects the i
acolwell GONE FROM CHROMIUM
2012/08/28 21:45:04
oh.. right..nevermind. I'm so used to 'continue' m
|
| + continue; |
| + |
| + // Determine the number of sample-frames we just decoded. Check overflow. |
| + int frames_read = av_frame->nb_samples; |
| + if (frames_read < 0) { |
| + continue_decoding = false; |
| + break; |
| + } |
| + |
| + // Truncate, if necessary, if the destination isn't big enough. |
| + if (current_frame + frames_read > audio_bus->frames()) |
| + frames_read = audio_bus->frames() - current_frame; |
| + |
| + // Deinterleave each channel and convert to 32bit floating-point |
| + // with nominal range -1.0 -> +1.0. |
| + audio_bus->FromInterleavedPartial( |
| + av_frame->data[0], current_frame, frames_read, bytes_per_sample); |
| + |
| + current_frame += frames_read; |
| + } while (packet_temp.size > 0); |
| + av_free_packet(&packet); |
| } |
| // Zero any remaining frames. |