| Index: webkit/media/crypto/decoders/ffmpeg_video_decoder.cc
|
| diff --git a/webkit/media/crypto/decoders/ffmpeg_video_decoder.cc b/webkit/media/crypto/decoders/ffmpeg_video_decoder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d16976b61b8ce97807b45bb40ee3bdc8e261455a
|
| --- /dev/null
|
| +++ b/webkit/media/crypto/decoders/ffmpeg_video_decoder.cc
|
| @@ -0,0 +1,127 @@
|
| +// Copyright (c) 2012 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 "base/logging.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "media/base/limits.h"
|
| +#include "media/ffmpeg/ffmpeg_common.h"
|
| +#include "webkit/media/crypto/decoders/ffmpeg_util.h"
|
| +#include "webkit/media/crypto/decoders/ffmpeg_video_decoder.h"
|
| +#include "webkit/media/crypto/ppapi/content_decryption_module.h"
|
| +
|
| +namespace webkit_media {
|
| +
|
| +using cdm::VideoDecoderConfig;
|
| +using cdm::VideoFrame;
|
| +
|
| +static int GetVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
|
| + FFmpegVideoDecoder* vd = static_cast<FFmpegVideoDecoder*>(s->opaque);
|
| + return vd->GetVideoBuffer(s, frame);
|
| +}
|
| +
|
| +static void ReleaseVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
|
| + scoped_refptr<VideoFrame> video_frame;
|
| + video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque));
|
| +
|
| + // The FFmpeg API expects us to zero the data pointers in
|
| + // this callback
|
| + memset(frame->data, 0, sizeof(frame->data));
|
| + frame->opaque = NULL;
|
| +}
|
| +
|
| +FFmpegVideoDecoder::FFmpegVideoDecoder()
|
| + : codec_context_(NULL),
|
| + av_frame_(NULL) {
|
| +}
|
| +
|
| +FFmpegVideoDecoder::~FFmpegVideoDecoder() {
|
| +}
|
| +
|
| +bool FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config) {
|
| + return false;
|
| +}
|
| +
|
| +bool FFmpegVideoDecoder::DecodeFrame(const VideoFrame& compressed_frame,
|
| + VideoFrame* decompressed_frame) {
|
| + return false;
|
| +}
|
| +
|
| +int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context,
|
| + AVFrame* frame) {
|
| + // Don't use |codec_context_| here! With threaded decoding,
|
| + // it will contain unsynchronized width/height/pix_fmt values,
|
| + // whereas |codec_context| contains the current threads's
|
| + // updated width/height/pix_fmt, which can change for adaptive
|
| + // content.
|
| + VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
|
| + if (format == VideoFrame::INVALID)
|
| + return AVERROR(EINVAL);
|
| + DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16);
|
| +
|
| + gfx::Size size(codec_context->width, codec_context->height);
|
| + int ret;
|
| + if ((ret = av_image_check_size(size.width(), size.height(), 0, NULL)) < 0)
|
| + return ret;
|
| +
|
| + gfx::Size natural_size;
|
| + if (codec_context->sample_aspect_ratio.num > 0) {
|
| + natural_size = GetNaturalSize(size,
|
| + codec_context->sample_aspect_ratio.num,
|
| + codec_context->sample_aspect_ratio.den);
|
| + } else {
|
| + natural_size = demuxer_stream_->video_decoder_config().natural_size();
|
| + }
|
| +
|
| + if (!VideoFrame::IsValidConfig(format, size, natural_size))
|
| + return AVERROR(EINVAL);
|
| +
|
| + scoped_refptr<VideoFrame> video_frame =
|
| + VideoFrame::CreateFrame(format, size, natural_size, kNoTimestamp());
|
| +
|
| + for (int i = 0; i < 3; i++) {
|
| + frame->base[i] = video_frame->data(i);
|
| + frame->data[i] = video_frame->data(i);
|
| + frame->linesize[i] = video_frame->stride(i);
|
| + }
|
| +
|
| + frame->opaque = NULL;
|
| + video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque));
|
| + frame->type = FF_BUFFER_TYPE_USER;
|
| + frame->pkt_pts = codec_context->pkt ? codec_context->pkt->pts :
|
| + AV_NOPTS_VALUE;
|
| + frame->width = codec_context->width;
|
| + frame->height = codec_context->height;
|
| + frame->format = codec_context->pix_fmt;
|
| +
|
| + return 0;
|
| +}
|
| +
|
| +// static
|
| +bool VideoFrame::IsValidConfig(VideoFrame::Format format,
|
| + const Size& data_size) {
|
| + return (format != VideoFrame::INVALID &&
|
| + data_size.width() > 0 && data_size.height() > 0 &&
|
| + data_size.width() <= limits::kMaxDimension &&
|
| + data_size.height() <= limits::kMaxDimension &&
|
| + data_size.width() * data_size.height() <= limits::kMaxCanvas &&
|
| + natural_size.width() > 0 && natural_size.height() > 0 &&
|
| + natural_size.width() <= limits::kMaxDimension &&
|
| + natural_size.height() <= limits::kMaxDimension &&
|
| + natural_size.width() * natural_size.height() <= limits::kMaxCanvas);
|
| +}
|
| +
|
| +void FFmpegVideoDecoder::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;
|
| + }
|
| +}
|
| +
|
| +} // namespace webkit_media
|
|
|