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

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

Issue 2752323002: Support Opus Ambisonics playback (Closed)
Patch Set: actually add config_ change Created 3 years, 8 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
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/ffmpeg_audio_decoder.h" 5 #include "media/filters/ffmpeg_audio_decoder.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 scoped_refptr<AudioBuffer> output; 220 scoped_refptr<AudioBuffer> output;
221 221
222 bool config_changed = false; 222 bool config_changed = false;
223 if (frame_decoded) { 223 if (frame_decoded) {
224 const int channels = DetermineChannels(av_frame_.get()); 224 const int channels = DetermineChannels(av_frame_.get());
225 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout( 225 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout(
226 codec_context_->channel_layout, codec_context_->channels); 226 codec_context_->channel_layout, codec_context_->channels);
227 227
228 bool is_sample_rate_change = 228 bool is_sample_rate_change =
229 av_frame_->sample_rate != config_.samples_per_second(); 229 av_frame_->sample_rate != config_.samples_per_second();
230 bool is_config_stale = 230 bool is_config_stale = is_sample_rate_change ||
231 is_sample_rate_change || 231 channels != config_.channels() ||
232 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || 232 av_frame_->format != av_sample_format_;
233 av_frame_->format != av_sample_format_;
234 233
235 // Only consider channel layout changes for AAC. 234 // Only consider channel layout changes for AAC.
236 // TODO(tguilbert, dalecurtis): Due to http://crbug.com/600538 we need to 235 // TODO(tguilbert, dalecurtis): Due to http://crbug.com/600538 we need to
237 // allow channel layout changes for the moment. See if ffmpeg is fixable. 236 // allow channel layout changes for the moment. See if ffmpeg is fixable.
238 if (config_.codec() == kCodecAAC) 237 if (config_.codec() == kCodecAAC)
239 is_config_stale |= channel_layout != config_.channel_layout(); 238 is_config_stale |= channel_layout != config_.channel_layout();
240 239
241 if (is_config_stale) { 240 if (is_config_stale) {
242 // Only allow midstream configuration changes for AAC. Sample format is 241 // Only allow midstream configuration changes for AAC. Sample format is
243 // not expected to change between AAC profiles. 242 // not expected to change between AAC profiles.
244 if (config_.codec() == kCodecAAC && 243 if (config_.codec() == kCodecAAC &&
245 av_frame_->format == av_sample_format_) { 244 av_frame_->format == av_sample_format_) {
246 MEDIA_LOG(DEBUG, media_log_) 245 MEDIA_LOG(DEBUG, media_log_)
247 << " Detected AAC midstream configuration change" 246 << " Detected AAC midstream configuration change"
248 << " PTS:" << buffer->timestamp().InMicroseconds() 247 << " PTS:" << buffer->timestamp().InMicroseconds()
249 << " Sample Rate: " << av_frame_->sample_rate << " vs " 248 << " Sample Rate: " << av_frame_->sample_rate << " vs "
250 << config_.samples_per_second() 249 << config_.samples_per_second()
251 << ", ChannelLayout: " << channel_layout << " vs " 250 << ", ChannelLayout: " << channel_layout << " vs "
252 << config_.channel_layout() << ", Channels: " << channels 251 << config_.channel_layout() << ", Channels: " << channels
253 << " vs " 252 << " vs " << config_.channels();
254 << ChannelLayoutToChannelCount(config_.channel_layout());
255 config_.Initialize(config_.codec(), config_.sample_format(), 253 config_.Initialize(config_.codec(), config_.sample_format(),
256 channel_layout, av_frame_->sample_rate, 254 channel_layout, av_frame_->sample_rate,
257 config_.extra_data(), config_.encryption_scheme(), 255 config_.extra_data(), config_.encryption_scheme(),
258 config_.seek_preroll(), config_.codec_delay()); 256 config_.seek_preroll(), config_.codec_delay());
259 config_changed = true; 257 config_changed = true;
260 if (is_sample_rate_change) 258 if (is_sample_rate_change)
261 ResetTimestampState(); 259 ResetTimestampState();
262 } else { 260 } else {
263 MEDIA_LOG(ERROR, media_log_) 261 MEDIA_LOG(ERROR, media_log_)
264 << "Unsupported midstream configuration change!" 262 << "Unsupported midstream configuration change!"
265 << " Sample Rate: " << av_frame_->sample_rate << " vs " 263 << " Sample Rate: " << av_frame_->sample_rate << " vs "
266 << config_.samples_per_second() << ", Channels: " << channels 264 << config_.samples_per_second() << ", Channels: " << channels
267 << " vs " << ChannelLayoutToChannelCount(config_.channel_layout()) 265 << " vs " << config_.channels()
268 << ", Sample Format: " << av_frame_->format << " vs " 266 << ", Sample Format: " << av_frame_->format << " vs "
269 << av_sample_format_; 267 << av_sample_format_;
270 // This is an unrecoverable error, so bail out. 268 // This is an unrecoverable error, so bail out.
271 av_frame_unref(av_frame_.get()); 269 av_frame_unref(av_frame_.get());
272 return false; 270 return false;
273 } 271 }
274 } 272 }
275 273
276 // Get the AudioBuffer that the data was decoded into. Adjust the number 274 // Get the AudioBuffer that the data was decoded into. Adjust the number
277 // of frames, in case fewer than requested were actually decoded. 275 // of frames, in case fewer than requested were actually decoded.
278 output = reinterpret_cast<AudioBuffer*>( 276 output = reinterpret_cast<AudioBuffer*>(
279 av_buffer_get_opaque(av_frame_->buf[0])); 277 av_buffer_get_opaque(av_frame_->buf[0]));
280 278
281 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), 279 DCHECK_EQ(config_.channels(), output->channel_count());
282 output->channel_count());
283 const int unread_frames = output->frame_count() - av_frame_->nb_samples; 280 const int unread_frames = output->frame_count() - av_frame_->nb_samples;
284 DCHECK_GE(unread_frames, 0); 281 DCHECK_GE(unread_frames, 0);
285 if (unread_frames > 0) 282 if (unread_frames > 0)
286 output->TrimEnd(unread_frames); 283 output->TrimEnd(unread_frames);
287 av_frame_unref(av_frame_.get()); 284 av_frame_unref(av_frame_.get());
288 } 285 }
289 286
290 // WARNING: |av_frame_| no longer has valid data at this point. 287 // WARNING: |av_frame_| no longer has valid data at this point.
291 const int decoded_frames = frame_decoded ? output->frame_count() : 0; 288 const int decoded_frames = frame_decoded ? output->frame_count() : 0;
292 if (IsEndOfStream(result, decoded_frames, buffer)) { 289 if (IsEndOfStream(result, decoded_frames, buffer)) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 << codec_context_->codec_id; 334 << codec_context_->codec_id;
338 ReleaseFFmpegResources(); 335 ReleaseFFmpegResources();
339 state_ = kUninitialized; 336 state_ = kUninitialized;
340 return false; 337 return false;
341 } 338 }
342 339
343 // Success! 340 // Success!
344 av_frame_.reset(av_frame_alloc()); 341 av_frame_.reset(av_frame_alloc());
345 av_sample_format_ = codec_context_->sample_fmt; 342 av_sample_format_ = codec_context_->sample_fmt;
346 343
347 if (codec_context_->channels != 344 if (codec_context_->channels != config_.channels()) {
348 ChannelLayoutToChannelCount(config_.channel_layout())) { 345 DLOG(ERROR) << "Audio configuration specified " << config_.channels()
349 DLOG(ERROR) << "Audio configuration specified "
350 << ChannelLayoutToChannelCount(config_.channel_layout())
351 << " channels, but FFmpeg thinks the file contains " 346 << " channels, but FFmpeg thinks the file contains "
352 << codec_context_->channels << " channels"; 347 << codec_context_->channels << " channels";
353 ReleaseFFmpegResources(); 348 ReleaseFFmpegResources();
354 state_ = kUninitialized; 349 state_ = kUninitialized;
355 return false; 350 return false;
356 } 351 }
357 352
358 ResetTimestampState(); 353 ResetTimestampState();
359 return true; 354 return true;
360 } 355 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 // we need to take this into consideration. 403 // we need to take this into consideration.
409 int buffer_size_in_bytes = av_samples_get_buffer_size( 404 int buffer_size_in_bytes = av_samples_get_buffer_size(
410 &frame->linesize[0], channels, frame->nb_samples, format, 405 &frame->linesize[0], channels, frame->nb_samples, format,
411 0 /* align, use ffmpeg default */); 406 0 /* align, use ffmpeg default */);
412 // Check for errors from av_samples_get_buffer_size(). 407 // Check for errors from av_samples_get_buffer_size().
413 if (buffer_size_in_bytes < 0) 408 if (buffer_size_in_bytes < 0)
414 return buffer_size_in_bytes; 409 return buffer_size_in_bytes;
415 int frames_required = buffer_size_in_bytes / bytes_per_channel / channels; 410 int frames_required = buffer_size_in_bytes / bytes_per_channel / channels;
416 DCHECK_GE(frames_required, frame->nb_samples); 411 DCHECK_GE(frames_required, frame->nb_samples);
417 412
418 ChannelLayout channel_layout = 413 if (config_.channel_layout() == CHANNEL_LAYOUT_UNSUPPORTED) {
419 ChannelLayoutToChromeChannelLayout(s->channel_layout, s->channels);
420
421 if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
422 DLOG(ERROR) << "Unsupported channel layout."; 414 DLOG(ERROR) << "Unsupported channel layout.";
423 return AVERROR(EINVAL); 415 return AVERROR(EINVAL);
424 } 416 }
425 417
426 scoped_refptr<AudioBuffer> buffer = 418 scoped_refptr<AudioBuffer> buffer = AudioBuffer::CreateBuffer(
427 AudioBuffer::CreateBuffer(sample_format, channel_layout, channels, 419 sample_format, config_.channel_layout(), channels, s->sample_rate,
428 s->sample_rate, frames_required, pool_); 420 frames_required, pool_);
429 421
430 // Initialize the data[] and extended_data[] fields to point into the memory 422 // Initialize the data[] and extended_data[] fields to point into the memory
431 // allocated for AudioBuffer. |number_of_planes| will be 1 for interleaved 423 // allocated for AudioBuffer. |number_of_planes| will be 1 for interleaved
432 // audio and equal to |channels| for planar audio. 424 // audio and equal to |channels| for planar audio.
433 int number_of_planes = buffer->channel_data().size(); 425 int number_of_planes = buffer->channel_data().size();
434 if (number_of_planes <= AV_NUM_DATA_POINTERS) { 426 if (number_of_planes <= AV_NUM_DATA_POINTERS) {
435 DCHECK_EQ(frame->extended_data, frame->data); 427 DCHECK_EQ(frame->extended_data, frame->data);
436 for (int i = 0; i < number_of_planes; ++i) 428 for (int i = 0; i < number_of_planes; ++i)
437 frame->data[i] = buffer->channel_data()[i]; 429 frame->data[i] = buffer->channel_data()[i];
438 } else { 430 } else {
(...skipping 11 matching lines...) Expand all
450 // Now create an AVBufferRef for the data just allocated. It will own the 442 // Now create an AVBufferRef for the data just allocated. It will own the
451 // reference to the AudioBuffer object. 443 // reference to the AudioBuffer object.
452 AudioBuffer* opaque = buffer.get(); 444 AudioBuffer* opaque = buffer.get();
453 opaque->AddRef(); 445 opaque->AddRef();
454 frame->buf[0] = av_buffer_create(frame->data[0], buffer_size_in_bytes, 446 frame->buf[0] = av_buffer_create(frame->data[0], buffer_size_in_bytes,
455 ReleaseAudioBufferImpl, opaque, 0); 447 ReleaseAudioBufferImpl, opaque, 0);
456 return 0; 448 return 0;
457 } 449 }
458 450
459 } // namespace media 451 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698