Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: media/filters/audio_file_reader.cc

Issue 10869085: Update FFmpegAudioDecoder to support multi-frame packets. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Comments. Fix WebAudio. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698