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

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

Issue 2752323002: Support Opus Ambisonics playback (Closed)
Patch Set: Fix issues from rebase Created 3 years, 6 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 scoped_refptr<AudioBuffer> output; 219 scoped_refptr<AudioBuffer> output;
220 220
221 bool config_changed = false; 221 bool config_changed = false;
222 if (frame_decoded) { 222 if (frame_decoded) {
223 const int channels = DetermineChannels(av_frame_.get()); 223 const int channels = DetermineChannels(av_frame_.get());
224 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout( 224 ChannelLayout channel_layout = ChannelLayoutToChromeChannelLayout(
225 codec_context_->channel_layout, codec_context_->channels); 225 codec_context_->channel_layout, codec_context_->channels);
226 226
227 bool is_sample_rate_change = 227 bool is_sample_rate_change =
228 av_frame_->sample_rate != config_.samples_per_second(); 228 av_frame_->sample_rate != config_.samples_per_second();
229 bool is_config_stale = 229 bool is_config_stale = is_sample_rate_change ||
230 is_sample_rate_change || 230 channels != config_.channels() ||
231 channels != ChannelLayoutToChannelCount(config_.channel_layout()) || 231 av_frame_->format != av_sample_format_;
232 av_frame_->format != av_sample_format_;
233 232
234 // Only consider channel layout changes for AAC. 233 // Only consider channel layout changes for AAC.
235 // TODO(tguilbert, dalecurtis): Due to http://crbug.com/600538 we need to 234 // TODO(tguilbert, dalecurtis): Due to http://crbug.com/600538 we need to
236 // allow channel layout changes for the moment. See if ffmpeg is fixable. 235 // allow channel layout changes for the moment. See if ffmpeg is fixable.
237 if (config_.codec() == kCodecAAC) 236 if (config_.codec() == kCodecAAC)
238 is_config_stale |= channel_layout != config_.channel_layout(); 237 is_config_stale |= channel_layout != config_.channel_layout();
239 238
240 if (is_config_stale) { 239 if (is_config_stale) {
241 // Only allow midstream configuration changes for AAC. Sample format is 240 // Only allow midstream configuration changes for AAC. Sample format is
242 // not expected to change between AAC profiles. 241 // not expected to change between AAC profiles.
243 if (config_.codec() == kCodecAAC && 242 if (config_.codec() == kCodecAAC &&
244 av_frame_->format == av_sample_format_) { 243 av_frame_->format == av_sample_format_) {
245 MEDIA_LOG(DEBUG, media_log_) 244 MEDIA_LOG(DEBUG, media_log_)
246 << " Detected AAC midstream configuration change" 245 << " Detected AAC midstream configuration change"
247 << " PTS:" << buffer->timestamp().InMicroseconds() 246 << " PTS:" << buffer->timestamp().InMicroseconds()
248 << " Sample Rate: " << av_frame_->sample_rate << " vs " 247 << " Sample Rate: " << av_frame_->sample_rate << " vs "
249 << config_.samples_per_second() 248 << config_.samples_per_second()
250 << ", ChannelLayout: " << channel_layout << " vs " 249 << ", ChannelLayout: " << channel_layout << " vs "
251 << config_.channel_layout() << ", Channels: " << channels 250 << config_.channel_layout() << ", Channels: " << channels
252 << " vs " 251 << " vs " << config_.channels();
253 << ChannelLayoutToChannelCount(config_.channel_layout());
254 config_.Initialize(config_.codec(), config_.sample_format(), 252 config_.Initialize(config_.codec(), config_.sample_format(),
255 channel_layout, av_frame_->sample_rate, 253 channel_layout, av_frame_->sample_rate,
256 config_.extra_data(), config_.encryption_scheme(), 254 config_.extra_data(), config_.encryption_scheme(),
257 config_.seek_preroll(), config_.codec_delay()); 255 config_.seek_preroll(), config_.codec_delay());
258 config_changed = true; 256 config_changed = true;
259 if (is_sample_rate_change) 257 if (is_sample_rate_change)
260 ResetTimestampState(config_); 258 ResetTimestampState(config_);
261 } else { 259 } else {
262 MEDIA_LOG(ERROR, media_log_) 260 MEDIA_LOG(ERROR, media_log_)
263 << "Unsupported midstream configuration change!" 261 << "Unsupported midstream configuration change!"
264 << " Sample Rate: " << av_frame_->sample_rate << " vs " 262 << " Sample Rate: " << av_frame_->sample_rate << " vs "
265 << config_.samples_per_second() << ", Channels: " << channels 263 << config_.samples_per_second() << ", Channels: " << channels
266 << " vs " << ChannelLayoutToChannelCount(config_.channel_layout()) 264 << " vs " << config_.channels()
267 << ", Sample Format: " << av_frame_->format << " vs " 265 << ", Sample Format: " << av_frame_->format << " vs "
268 << av_sample_format_; 266 << av_sample_format_;
269 // This is an unrecoverable error, so bail out. 267 // This is an unrecoverable error, so bail out.
270 av_frame_unref(av_frame_.get()); 268 av_frame_unref(av_frame_.get());
271 return false; 269 return false;
272 } 270 }
273 } 271 }
274 272
275 // Get the AudioBuffer that the data was decoded into. Adjust the number 273 // Get the AudioBuffer that the data was decoded into. Adjust the number
276 // of frames, in case fewer than requested were actually decoded. 274 // of frames, in case fewer than requested were actually decoded.
277 output = reinterpret_cast<AudioBuffer*>( 275 output = reinterpret_cast<AudioBuffer*>(
278 av_buffer_get_opaque(av_frame_->buf[0])); 276 av_buffer_get_opaque(av_frame_->buf[0]));
279 277
280 DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()), 278 DCHECK_EQ(config_.channels(), output->channel_count());
281 output->channel_count());
282 const int unread_frames = output->frame_count() - av_frame_->nb_samples; 279 const int unread_frames = output->frame_count() - av_frame_->nb_samples;
283 DCHECK_GE(unread_frames, 0); 280 DCHECK_GE(unread_frames, 0);
284 if (unread_frames > 0) 281 if (unread_frames > 0)
285 output->TrimEnd(unread_frames); 282 output->TrimEnd(unread_frames);
286 av_frame_unref(av_frame_.get()); 283 av_frame_unref(av_frame_.get());
287 } 284 }
288 285
289 // WARNING: |av_frame_| no longer has valid data at this point. 286 // WARNING: |av_frame_| no longer has valid data at this point.
290 const int decoded_frames = frame_decoded ? output->frame_count() : 0; 287 const int decoded_frames = frame_decoded ? output->frame_count() : 0;
291 if (IsEndOfStream(result, decoded_frames, buffer)) { 288 if (IsEndOfStream(result, decoded_frames, buffer)) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 << codec_context_->codec_id; 333 << codec_context_->codec_id;
337 ReleaseFFmpegResources(); 334 ReleaseFFmpegResources();
338 state_ = kUninitialized; 335 state_ = kUninitialized;
339 return false; 336 return false;
340 } 337 }
341 338
342 // Success! 339 // Success!
343 av_frame_.reset(av_frame_alloc()); 340 av_frame_.reset(av_frame_alloc());
344 av_sample_format_ = codec_context_->sample_fmt; 341 av_sample_format_ = codec_context_->sample_fmt;
345 342
346 if (codec_context_->channels != 343 if (codec_context_->channels != config.channels()) {
347 ChannelLayoutToChannelCount(config.channel_layout())) {
348 MEDIA_LOG(ERROR, media_log_) 344 MEDIA_LOG(ERROR, media_log_)
349 << "Audio configuration specified " 345 << "Audio configuration specified " << config.channels()
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(config); 353 ResetTimestampState(config);
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