Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/filters/audio_file_reader.h" | 5 #include "media/filters/audio_file_reader.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/time.h" | 10 #include "base/time.h" |
| 11 #include "media/base/audio_bus.h" | 11 #include "media/base/audio_bus.h" |
| 12 #include "media/ffmpeg/ffmpeg_common.h" | 12 #include "media/ffmpeg/ffmpeg_common.h" |
| 13 #include "media/filters/ffmpeg_glue.h" | 13 #include "media/filters/ffmpeg_glue.h" |
| 14 | 14 |
| 15 namespace media { | 15 namespace media { |
| 16 | 16 |
| 17 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) | 17 AudioFileReader::AudioFileReader(FFmpegURLProtocol* protocol) |
| 18 : protocol_(protocol), | 18 : protocol_(protocol), |
| 19 format_context_(NULL), | 19 format_context_(NULL), |
| 20 codec_context_(NULL) { | 20 codec_context_(NULL), |
| 21 stream_index_(0) { | |
| 21 } | 22 } |
| 22 | 23 |
| 23 AudioFileReader::~AudioFileReader() { | 24 AudioFileReader::~AudioFileReader() { |
| 24 Close(); | 25 Close(); |
| 25 } | 26 } |
| 26 | 27 |
| 27 int AudioFileReader::channels() const { | 28 int AudioFileReader::channels() const { |
| 28 return codec_context_->channels; | 29 return codec_context_->channels; |
| 29 } | 30 } |
| 30 | 31 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 | 65 |
| 65 DCHECK(context); | 66 DCHECK(context); |
| 66 format_context_ = context; | 67 format_context_ = context; |
| 67 | 68 |
| 68 // Get the codec context. | 69 // Get the codec context. |
| 69 codec_context_ = NULL; | 70 codec_context_ = NULL; |
| 70 for (size_t i = 0; i < format_context_->nb_streams; ++i) { | 71 for (size_t i = 0; i < format_context_->nb_streams; ++i) { |
| 71 AVCodecContext* c = format_context_->streams[i]->codec; | 72 AVCodecContext* c = format_context_->streams[i]->codec; |
| 72 if (c->codec_type == AVMEDIA_TYPE_AUDIO) { | 73 if (c->codec_type == AVMEDIA_TYPE_AUDIO) { |
| 73 codec_context_ = c; | 74 codec_context_ = c; |
| 75 stream_index_ = i; | |
| 74 break; | 76 break; |
| 75 } | 77 } |
| 76 } | 78 } |
| 77 | 79 |
| 78 // Get the codec. | 80 // Get the codec. |
| 79 if (!codec_context_) | 81 if (!codec_context_) |
| 80 return false; | 82 return false; |
| 81 | 83 |
| 82 avformat_find_stream_info(format_context_, NULL); | 84 avformat_find_stream_info(format_context_, NULL); |
| 83 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 85 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 if (audio_bus->channels() != channels) | 119 if (audio_bus->channels() != channels) |
| 118 return false; | 120 return false; |
| 119 | 121 |
| 120 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); | 122 size_t bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); |
| 121 | 123 |
| 122 // Holds decoded audio. | 124 // Holds decoded audio. |
| 123 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> av_frame(avcodec_alloc_frame()); | 125 scoped_ptr_malloc<AVFrame, ScopedPtrAVFree> av_frame(avcodec_alloc_frame()); |
| 124 | 126 |
| 125 // Read until we hit EOF or we've read the requested number of frames. | 127 // Read until we hit EOF or we've read the requested number of frames. |
| 126 AVPacket packet; | 128 AVPacket packet; |
| 127 int result = 0; | |
| 128 int current_frame = 0; | 129 int current_frame = 0; |
| 130 bool continue_decoding = true; | |
| 129 | 131 |
| 130 while (current_frame < audio_bus->frames() && | 132 while (current_frame < audio_bus->frames() && continue_decoding && |
| 131 (result = av_read_frame(format_context_, &packet)) >= 0) { | 133 av_read_frame(format_context_, &packet) >= 0 && |
| 132 avcodec_get_frame_defaults(av_frame.get()); | 134 av_dup_packet(&packet) >= 0) { |
| 133 int frame_decoded = 0; | 135 // Skip packets from other streams. |
|
DaleCurtis
2012/08/28 20:19:17
Noticed this while testing, previously handing a c
| |
| 134 int result = avcodec_decode_audio4( | 136 if (packet.stream_index != stream_index_) { |
| 135 codec_context_, av_frame.get(), &frame_decoded, &packet); | 137 av_free_packet(&packet); |
| 136 av_free_packet(&packet); | 138 continue; |
| 137 | |
| 138 if (result < 0) { | |
| 139 DLOG(WARNING) | |
| 140 << "AudioFileReader::Read() : error in avcodec_decode_audio3() -" | |
| 141 << result; | |
| 142 break; | |
| 143 } | 139 } |
| 144 | 140 |
| 145 if (!frame_decoded) | 141 // Make a shallow copy of packet so we can slide packet.data as frames are |
| 146 continue; | 142 // decoded from the packet; otherwise av_free_packet() will corrupt memory. |
| 143 AVPacket packet_temp = packet; | |
| 144 do { | |
| 145 avcodec_get_frame_defaults(av_frame.get()); | |
| 146 int frame_decoded = 0; | |
| 147 int result = avcodec_decode_audio4( | |
| 148 codec_context_, av_frame.get(), &frame_decoded, &packet_temp); | |
| 147 | 149 |
| 148 // Determine the number of sample-frames we just decoded. Check overflow. | 150 if (result < 0) { |
| 149 int frames_read = av_frame->nb_samples; | 151 DLOG(WARNING) |
| 150 if (frames_read < 0) | 152 << "AudioFileReader::Read() : error in avcodec_decode_audio4() -" |
| 151 break; | 153 << result; |
| 154 continue_decoding = false; | |
| 155 break; | |
| 156 } | |
| 152 | 157 |
| 153 // Truncate, if necessary, if the destination isn't big enough. | 158 // Update packet size and data pointer in case we need to call the decoder |
| 154 if (current_frame + frames_read > audio_bus->frames()) | 159 // with the remaining bytes from this packet. |
| 155 frames_read = audio_bus->frames() - current_frame; | 160 packet_temp.size -= result; |
| 161 packet_temp.data += result; | |
| 156 | 162 |
| 157 // Deinterleave each channel and convert to 32bit floating-point | 163 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
| |
| 158 // with nominal range -1.0 -> +1.0. | 164 continue; |
| 159 audio_bus->FromInterleavedPartial( | |
| 160 av_frame->data[0], current_frame, frames_read, bytes_per_sample); | |
| 161 | 165 |
| 162 current_frame += frames_read; | 166 // Determine the number of sample-frames we just decoded. Check overflow. |
| 167 int frames_read = av_frame->nb_samples; | |
| 168 if (frames_read < 0) { | |
| 169 continue_decoding = false; | |
| 170 break; | |
| 171 } | |
| 172 | |
| 173 // Truncate, if necessary, if the destination isn't big enough. | |
| 174 if (current_frame + frames_read > audio_bus->frames()) | |
| 175 frames_read = audio_bus->frames() - current_frame; | |
| 176 | |
| 177 // Deinterleave each channel and convert to 32bit floating-point | |
| 178 // with nominal range -1.0 -> +1.0. | |
| 179 audio_bus->FromInterleavedPartial( | |
| 180 av_frame->data[0], current_frame, frames_read, bytes_per_sample); | |
| 181 | |
| 182 current_frame += frames_read; | |
| 183 } while (packet_temp.size > 0); | |
| 184 av_free_packet(&packet); | |
| 163 } | 185 } |
| 164 | 186 |
| 165 // Zero any remaining frames. | 187 // Zero any remaining frames. |
| 166 audio_bus->ZeroFramesPartial( | 188 audio_bus->ZeroFramesPartial( |
| 167 current_frame, audio_bus->frames() - current_frame); | 189 current_frame, audio_bus->frames() - current_frame); |
| 168 | 190 |
| 169 // Fail if nothing has been decoded, otherwise return partial data. | 191 // Fail if nothing has been decoded, otherwise return partial data. |
| 170 return current_frame > 0; | 192 return current_frame > 0; |
| 171 } | 193 } |
| 172 | 194 |
| 173 } // namespace media | 195 } // namespace media |
| OLD | NEW |