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

Unified Diff: webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc

Issue 22362007: Relocate last remnants of webkit/renderer/media code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make chromeos crypto dep explicit. Created 7 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
diff --git a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc b/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
deleted file mode 100644
index 1391de88a9a28279751ca945e6a47c51c6c71d9d..0000000000000000000000000000000000000000
--- a/webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.cc
+++ /dev/null
@@ -1,413 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/renderer/media/crypto/ppapi/ffmpeg_cdm_audio_decoder.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "media/base/audio_bus.h"
-#include "media/base/audio_timestamp_helper.h"
-#include "media/base/buffers.h"
-#include "media/base/data_buffer.h"
-#include "media/base/limits.h"
-#include "webkit/renderer/media/crypto/ppapi/cdm/content_decryption_module.h"
-
-// Include FFmpeg header files.
-extern "C" {
-// Temporarily disable possible loss of data warning.
-MSVC_PUSH_DISABLE_WARNING(4244);
-#include <libavcodec/avcodec.h>
-MSVC_POP_WARNING();
-} // extern "C"
-
-namespace webkit_media {
-
-// Maximum number of channels with defined layout in src/media.
-static const int kMaxChannels = 8;
-
-static AVCodecID CdmAudioCodecToCodecID(
- cdm::AudioDecoderConfig::AudioCodec audio_codec) {
- switch (audio_codec) {
- case cdm::AudioDecoderConfig::kCodecVorbis:
- return AV_CODEC_ID_VORBIS;
- case cdm::AudioDecoderConfig::kCodecAac:
- return AV_CODEC_ID_AAC;
- case cdm::AudioDecoderConfig::kUnknownAudioCodec:
- default:
- NOTREACHED() << "Unsupported cdm::AudioCodec: " << audio_codec;
- return AV_CODEC_ID_NONE;
- }
-}
-
-static void CdmAudioDecoderConfigToAVCodecContext(
- const cdm::AudioDecoderConfig& config,
- AVCodecContext* codec_context) {
- codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
- codec_context->codec_id = CdmAudioCodecToCodecID(config.codec);
-
- switch (config.bits_per_channel) {
- case 8:
- codec_context->sample_fmt = AV_SAMPLE_FMT_U8;
- break;
- case 16:
- codec_context->sample_fmt = AV_SAMPLE_FMT_S16;
- break;
- case 32:
- codec_context->sample_fmt = AV_SAMPLE_FMT_S32;
- break;
- default:
- DVLOG(1) << "CdmAudioDecoderConfigToAVCodecContext() Unsupported bits "
- "per channel: " << config.bits_per_channel;
- codec_context->sample_fmt = AV_SAMPLE_FMT_NONE;
- }
-
- codec_context->channels = config.channel_count;
- codec_context->sample_rate = config.samples_per_second;
-
- if (config.extra_data) {
- codec_context->extradata_size = config.extra_data_size;
- codec_context->extradata = reinterpret_cast<uint8_t*>(
- av_malloc(config.extra_data_size + FF_INPUT_BUFFER_PADDING_SIZE));
- memcpy(codec_context->extradata, config.extra_data,
- config.extra_data_size);
- memset(codec_context->extradata + config.extra_data_size, '\0',
- FF_INPUT_BUFFER_PADDING_SIZE);
- } else {
- codec_context->extradata = NULL;
- codec_context->extradata_size = 0;
- }
-}
-
-FFmpegCdmAudioDecoder::FFmpegCdmAudioDecoder(cdm::Host* host)
- : is_initialized_(false),
- host_(host),
- codec_context_(NULL),
- av_frame_(NULL),
- bits_per_channel_(0),
- samples_per_second_(0),
- channels_(0),
- av_sample_format_(0),
- bytes_per_frame_(0),
- last_input_timestamp_(media::kNoTimestamp()),
- output_bytes_to_drop_(0) {
-}
-
-FFmpegCdmAudioDecoder::~FFmpegCdmAudioDecoder() {
- ReleaseFFmpegResources();
-}
-
-bool FFmpegCdmAudioDecoder::Initialize(const cdm::AudioDecoderConfig& config) {
- DVLOG(1) << "Initialize()";
-
- if (!IsValidConfig(config)) {
- LOG(ERROR) << "Initialize(): invalid audio decoder configuration.";
- return false;
- }
-
- if (is_initialized_) {
- LOG(ERROR) << "Initialize(): Already initialized.";
- return false;
- }
-
- // Initialize AVCodecContext structure.
- codec_context_ = avcodec_alloc_context3(NULL);
- CdmAudioDecoderConfigToAVCodecContext(config, codec_context_);
-
- // MP3 decodes to S16P which we don't support, tell it to use S16 instead.
- if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P)
- codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16;
-
- AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
- if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) {
- DLOG(ERROR) << "Could not initialize audio decoder: "
- << codec_context_->codec_id;
- return false;
- }
-
- // Ensure avcodec_open2() respected our format request.
- if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P) {
- DLOG(ERROR) << "Unable to configure a supported sample format: "
- << codec_context_->sample_fmt;
- return false;
- }
-
- // Some codecs will only output float data, so we need to convert to integer
- // before returning the decoded buffer.
- if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP ||
- codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) {
- // Preallocate the AudioBus for float conversions. We can treat interleaved
- // float data as a single planar channel since our output is expected in an
- // interleaved format anyways.
- int channels = codec_context_->channels;
- if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT)
- channels = 1;
- converter_bus_ = media::AudioBus::CreateWrapper(channels);
- }
-
- // Success!
- av_frame_ = avcodec_alloc_frame();
- bits_per_channel_ = config.bits_per_channel;
- samples_per_second_ = config.samples_per_second;
- bytes_per_frame_ = codec_context_->channels * bits_per_channel_ / 8;
- output_timestamp_helper_.reset(
- new media::AudioTimestampHelper(config.samples_per_second));
- serialized_audio_frames_.reserve(bytes_per_frame_ * samples_per_second_);
- is_initialized_ = true;
-
- // Store initial values to guard against midstream configuration changes.
- channels_ = codec_context_->channels;
- av_sample_format_ = codec_context_->sample_fmt;
-
- return true;
-}
-
-void FFmpegCdmAudioDecoder::Deinitialize() {
- DVLOG(1) << "Deinitialize()";
- ReleaseFFmpegResources();
- is_initialized_ = false;
- ResetTimestampState();
-}
-
-void FFmpegCdmAudioDecoder::Reset() {
- DVLOG(1) << "Reset()";
- avcodec_flush_buffers(codec_context_);
- ResetTimestampState();
-}
-
-// static
-bool FFmpegCdmAudioDecoder::IsValidConfig(
- const cdm::AudioDecoderConfig& config) {
- return config.codec != cdm::AudioDecoderConfig::kUnknownAudioCodec &&
- config.channel_count > 0 &&
- config.channel_count <= kMaxChannels &&
- config.bits_per_channel > 0 &&
- config.bits_per_channel <= media::limits::kMaxBitsPerSample &&
- config.samples_per_second > 0 &&
- config.samples_per_second <= media::limits::kMaxSampleRate;
-}
-
-cdm::Status FFmpegCdmAudioDecoder::DecodeBuffer(
- const uint8_t* compressed_buffer,
- int32_t compressed_buffer_size,
- int64_t input_timestamp,
- cdm::AudioFrames* decoded_frames) {
- DVLOG(1) << "DecodeBuffer()";
- const bool is_end_of_stream = !compressed_buffer;
- base::TimeDelta timestamp =
- base::TimeDelta::FromMicroseconds(input_timestamp);
-
- bool is_vorbis = codec_context_->codec_id == AV_CODEC_ID_VORBIS;
- if (!is_end_of_stream) {
- if (last_input_timestamp_ == media::kNoTimestamp()) {
- if (is_vorbis && timestamp < base::TimeDelta()) {
- // Dropping frames for negative timestamps as outlined in section A.2
- // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
- int frames_to_drop = floor(
- 0.5 + -timestamp.InSecondsF() * samples_per_second_);
- output_bytes_to_drop_ = bytes_per_frame_ * frames_to_drop;
- } else {
- last_input_timestamp_ = timestamp;
- }
- } else if (timestamp != media::kNoTimestamp()) {
- if (timestamp < last_input_timestamp_) {
- base::TimeDelta diff = timestamp - last_input_timestamp_;
- DVLOG(1) << "Input timestamps are not monotonically increasing! "
- << " ts " << timestamp.InMicroseconds() << " us"
- << " diff " << diff.InMicroseconds() << " us";
- return cdm::kDecodeError;
- }
-
- last_input_timestamp_ = timestamp;
- }
- }
-
- AVPacket packet;
- av_init_packet(&packet);
- packet.data = const_cast<uint8_t*>(compressed_buffer);
- packet.size = compressed_buffer_size;
-
- // Each audio packet may contain several frames, so we must call the decoder
- // until we've exhausted the packet. Regardless of the packet size we always
- // want to hand it to the decoder at least once, otherwise we would end up
- // skipping end of stream packets since they have a size of zero.
- do {
- // Reset frame to default values.
- avcodec_get_frame_defaults(av_frame_);
-
- int frame_decoded = 0;
- int result = avcodec_decode_audio4(
- codec_context_, av_frame_, &frame_decoded, &packet);
-
- if (result < 0) {
- DCHECK(!is_end_of_stream)
- << "End of stream buffer produced an error! "
- << "This is quite possibly a bug in the audio decoder not handling "
- << "end of stream AVPackets correctly.";
-
- DLOG(ERROR)
- << "Error decoding an audio frame with timestamp: "
- << timestamp.InMicroseconds() << " us, duration: "
- << timestamp.InMicroseconds() << " us, packet size: "
- << compressed_buffer_size << " bytes";
-
- return cdm::kDecodeError;
- }
-
- // Update packet size and data pointer in case we need to call the decoder
- // with the remaining bytes from this packet.
- packet.size -= result;
- packet.data += result;
-
- if (output_timestamp_helper_->base_timestamp() == media::kNoTimestamp() &&
- !is_end_of_stream) {
- DCHECK(timestamp != media::kNoTimestamp());
- if (output_bytes_to_drop_ > 0) {
- // Currently Vorbis is the only codec that causes us to drop samples.
- // If we have to drop samples it always means the timeline starts at 0.
- DCHECK_EQ(codec_context_->codec_id, AV_CODEC_ID_VORBIS);
- output_timestamp_helper_->SetBaseTimestamp(base::TimeDelta());
- } else {
- output_timestamp_helper_->SetBaseTimestamp(timestamp);
- }
- }
-
- int decoded_audio_size = 0;
- if (frame_decoded) {
- if (av_frame_->sample_rate != samples_per_second_ ||
- av_frame_->channels != channels_ ||
- av_frame_->format != av_sample_format_) {
- DLOG(ERROR) << "Unsupported midstream configuration change!"
- << " Sample Rate: " << av_frame_->sample_rate << " vs "
- << samples_per_second_
- << ", Channels: " << av_frame_->channels << " vs "
- << channels_
- << ", Sample Format: " << av_frame_->format << " vs "
- << av_sample_format_;
- return cdm::kDecodeError;
- }
-
- decoded_audio_size = av_samples_get_buffer_size(
- NULL, codec_context_->channels, av_frame_->nb_samples,
- codec_context_->sample_fmt, 1);
- // If we're decoding into float, adjust audio size.
- if (converter_bus_ && bits_per_channel_ / 8 != sizeof(float)) {
- DCHECK(codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT ||
- codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP);
- decoded_audio_size *=
- static_cast<float>(bits_per_channel_ / 8) / sizeof(float);
- }
- }
-
- int start_sample = 0;
- if (decoded_audio_size > 0 && output_bytes_to_drop_ > 0) {
- DCHECK_EQ(decoded_audio_size % bytes_per_frame_, 0)
- << "Decoder didn't output full frames";
-
- int dropped_size = std::min(decoded_audio_size, output_bytes_to_drop_);
- start_sample = dropped_size / bytes_per_frame_;
- decoded_audio_size -= dropped_size;
- output_bytes_to_drop_ -= dropped_size;
- }
-
- scoped_refptr<media::DataBuffer> output;
- if (decoded_audio_size > 0) {
- DCHECK_EQ(decoded_audio_size % bytes_per_frame_, 0)
- << "Decoder didn't output full frames";
-
- // Convert float data using an AudioBus.
- if (converter_bus_) {
- // Setup the AudioBus as a wrapper of the AVFrame data and then use
- // AudioBus::ToInterleaved() to convert the data as necessary.
- int skip_frames = start_sample;
- int total_frames = av_frame_->nb_samples;
- int frames_to_interleave = decoded_audio_size / bytes_per_frame_;
- if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLT) {
- DCHECK_EQ(converter_bus_->channels(), 1);
- total_frames *= codec_context_->channels;
- skip_frames *= codec_context_->channels;
- frames_to_interleave *= codec_context_->channels;
- }
-
- converter_bus_->set_frames(total_frames);
- for (int i = 0; i < converter_bus_->channels(); ++i) {
- converter_bus_->SetChannelData(i, reinterpret_cast<float*>(
- av_frame_->extended_data[i]));
- }
-
- output = new media::DataBuffer(decoded_audio_size);
- output->set_data_size(decoded_audio_size);
-
- DCHECK_EQ(frames_to_interleave, converter_bus_->frames() - skip_frames);
- converter_bus_->ToInterleavedPartial(
- skip_frames, frames_to_interleave, bits_per_channel_ / 8,
- output->writable_data());
- } else {
- output = media::DataBuffer::CopyFrom(
- av_frame_->extended_data[0] + start_sample * bytes_per_frame_,
- decoded_audio_size);
- }
-
- base::TimeDelta output_timestamp =
- output_timestamp_helper_->GetTimestamp();
- output_timestamp_helper_->AddFrames(decoded_audio_size /
- bytes_per_frame_);
-
- // Serialize the audio samples into |serialized_audio_frames_|.
- SerializeInt64(output_timestamp.InMicroseconds());
- SerializeInt64(output->data_size());
- serialized_audio_frames_.insert(
- serialized_audio_frames_.end(),
- output->data(),
- output->data() + output->data_size());
- }
- } while (packet.size > 0);
-
- if (!serialized_audio_frames_.empty()) {
- decoded_frames->SetFrameBuffer(
- host_->Allocate(serialized_audio_frames_.size()));
- if (!decoded_frames->FrameBuffer()) {
- LOG(ERROR) << "DecodeBuffer() cdm::Host::Allocate failed.";
- return cdm::kDecodeError;
- }
- memcpy(decoded_frames->FrameBuffer()->Data(),
- &serialized_audio_frames_[0],
- serialized_audio_frames_.size());
- decoded_frames->FrameBuffer()->SetSize(serialized_audio_frames_.size());
- serialized_audio_frames_.clear();
-
- return cdm::kSuccess;
- }
-
- return cdm::kNeedMoreData;
-}
-
-void FFmpegCdmAudioDecoder::ResetTimestampState() {
- output_timestamp_helper_->SetBaseTimestamp(media::kNoTimestamp());
- last_input_timestamp_ = media::kNoTimestamp();
- output_bytes_to_drop_ = 0;
-}
-
-void FFmpegCdmAudioDecoder::ReleaseFFmpegResources() {
- DVLOG(1) << "ReleaseFFmpegResources()";
-
- if (codec_context_) {
- av_free(codec_context_->extradata);
- avcodec_close(codec_context_);
- av_free(codec_context_);
- codec_context_ = NULL;
- }
- if (av_frame_) {
- av_free(av_frame_);
- av_frame_ = NULL;
- }
-}
-
-void FFmpegCdmAudioDecoder::SerializeInt64(int64 value) {
- int previous_size = serialized_audio_frames_.size();
- serialized_audio_frames_.resize(previous_size + sizeof(value));
- memcpy(&serialized_audio_frames_[0] + previous_size, &value, sizeof(value));
-}
-
-} // namespace webkit_media

Powered by Google App Engine
This is Rietveld 408576698