Index: media/cast/video_receiver/video_decoder.cc |
diff --git a/media/cast/video_receiver/video_decoder.cc b/media/cast/video_receiver/video_decoder.cc |
deleted file mode 100644 |
index c2d256268f645b387e3788c4d843851128d14b45..0000000000000000000000000000000000000000 |
--- a/media/cast/video_receiver/video_decoder.cc |
+++ /dev/null |
@@ -1,259 +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 "media/cast/video_receiver/video_decoder.h" |
- |
-#include "base/bind.h" |
-#include "base/bind_helpers.h" |
-#include "base/json/json_reader.h" |
-#include "base/location.h" |
-#include "base/logging.h" |
-#include "base/values.h" |
-#include "media/base/video_util.h" |
-#include "media/cast/cast_defines.h" |
-#include "media/cast/cast_environment.h" |
-// VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide |
-// backwards compatibility for legacy applications using the library. |
-#define VPX_CODEC_DISABLE_COMPAT 1 |
-#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" |
-#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" |
-#include "ui/gfx/size.h" |
- |
-namespace media { |
-namespace cast { |
- |
-// Base class that handles the common problem of detecting dropped frames, and |
-// then invoking the Decode() method implemented by the subclasses to convert |
-// the encoded payload data into a usable video frame. |
-class VideoDecoder::ImplBase |
- : public base::RefCountedThreadSafe<VideoDecoder::ImplBase> { |
- public: |
- ImplBase(const scoped_refptr<CastEnvironment>& cast_environment, |
- transport::VideoCodec codec) |
- : cast_environment_(cast_environment), |
- codec_(codec), |
- cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED), |
- seen_first_frame_(false) {} |
- |
- CastInitializationStatus InitializationResult() const { |
- return cast_initialization_status_; |
- } |
- |
- void DecodeFrame(scoped_ptr<transport::EncodedFrame> encoded_frame, |
- const DecodeFrameCallback& callback) { |
- DCHECK_EQ(cast_initialization_status_, STATUS_VIDEO_INITIALIZED); |
- |
- COMPILE_ASSERT(sizeof(encoded_frame->frame_id) == sizeof(last_frame_id_), |
- size_of_frame_id_types_do_not_match); |
- bool is_continuous = true; |
- if (seen_first_frame_) { |
- const uint32 frames_ahead = encoded_frame->frame_id - last_frame_id_; |
- if (frames_ahead > 1) { |
- RecoverBecauseFramesWereDropped(); |
- is_continuous = false; |
- } |
- } else { |
- seen_first_frame_ = true; |
- } |
- last_frame_id_ = encoded_frame->frame_id; |
- |
- const scoped_refptr<VideoFrame> decoded_frame = Decode( |
- encoded_frame->mutable_bytes(), |
- static_cast<int>(encoded_frame->data.size())); |
- cast_environment_->PostTask( |
- CastEnvironment::MAIN, |
- FROM_HERE, |
- base::Bind(callback, decoded_frame, is_continuous)); |
- } |
- |
- protected: |
- friend class base::RefCountedThreadSafe<ImplBase>; |
- virtual ~ImplBase() {} |
- |
- virtual void RecoverBecauseFramesWereDropped() {} |
- |
- // Note: Implementation of Decode() is allowed to mutate |data|. |
- virtual scoped_refptr<VideoFrame> Decode(uint8* data, int len) = 0; |
- |
- const scoped_refptr<CastEnvironment> cast_environment_; |
- const transport::VideoCodec codec_; |
- |
- // Subclass' ctor is expected to set this to STATUS_VIDEO_INITIALIZED. |
- CastInitializationStatus cast_initialization_status_; |
- |
- private: |
- bool seen_first_frame_; |
- uint32 last_frame_id_; |
- |
- DISALLOW_COPY_AND_ASSIGN(ImplBase); |
-}; |
- |
-class VideoDecoder::Vp8Impl : public VideoDecoder::ImplBase { |
- public: |
- explicit Vp8Impl(const scoped_refptr<CastEnvironment>& cast_environment) |
- : ImplBase(cast_environment, transport::kVp8) { |
- if (ImplBase::cast_initialization_status_ != STATUS_VIDEO_UNINITIALIZED) |
- return; |
- |
- vpx_codec_dec_cfg_t cfg = {0}; |
- // TODO(miu): Revisit this for typical multi-core desktop use case. This |
- // feels like it should be 4 or 8. |
- cfg.threads = 1; |
- |
- DCHECK(vpx_codec_get_caps(vpx_codec_vp8_dx()) & VPX_CODEC_CAP_POSTPROC); |
- if (vpx_codec_dec_init(&context_, |
- vpx_codec_vp8_dx(), |
- &cfg, |
- VPX_CODEC_USE_POSTPROC) != VPX_CODEC_OK) { |
- ImplBase::cast_initialization_status_ = |
- STATUS_INVALID_VIDEO_CONFIGURATION; |
- return; |
- } |
- ImplBase::cast_initialization_status_ = STATUS_VIDEO_INITIALIZED; |
- } |
- |
- private: |
- virtual ~Vp8Impl() { |
- if (ImplBase::cast_initialization_status_ == STATUS_VIDEO_INITIALIZED) |
- CHECK_EQ(VPX_CODEC_OK, vpx_codec_destroy(&context_)); |
- } |
- |
- virtual scoped_refptr<VideoFrame> Decode(uint8* data, int len) OVERRIDE { |
- if (len <= 0 || vpx_codec_decode(&context_, |
- data, |
- static_cast<unsigned int>(len), |
- NULL, |
- 0) != VPX_CODEC_OK) { |
- return NULL; |
- } |
- |
- vpx_codec_iter_t iter = NULL; |
- vpx_image_t* const image = vpx_codec_get_frame(&context_, &iter); |
- if (!image) |
- return NULL; |
- if (image->fmt != VPX_IMG_FMT_I420 && image->fmt != VPX_IMG_FMT_YV12) { |
- NOTREACHED(); |
- return NULL; |
- } |
- DCHECK(vpx_codec_get_frame(&context_, &iter) == NULL) |
- << "Should have only decoded exactly one frame."; |
- |
- const gfx::Size frame_size(image->d_w, image->d_h); |
- // Note: Timestamp for the VideoFrame will be set in VideoReceiver. |
- const scoped_refptr<VideoFrame> decoded_frame = |
- VideoFrame::CreateFrame(VideoFrame::YV12, |
- frame_size, |
- gfx::Rect(frame_size), |
- frame_size, |
- base::TimeDelta()); |
- CopyYPlane(image->planes[VPX_PLANE_Y], |
- image->stride[VPX_PLANE_Y], |
- image->d_h, |
- decoded_frame); |
- CopyUPlane(image->planes[VPX_PLANE_U], |
- image->stride[VPX_PLANE_U], |
- (image->d_h + 1) / 2, |
- decoded_frame); |
- CopyVPlane(image->planes[VPX_PLANE_V], |
- image->stride[VPX_PLANE_V], |
- (image->d_h + 1) / 2, |
- decoded_frame); |
- return decoded_frame; |
- } |
- |
- // VPX decoder context (i.e., an instantiation). |
- vpx_codec_ctx_t context_; |
- |
- DISALLOW_COPY_AND_ASSIGN(Vp8Impl); |
-}; |
- |
-#ifndef OFFICIAL_BUILD |
-// A fake video decoder that always output 2x2 black frames. |
-class VideoDecoder::FakeImpl : public VideoDecoder::ImplBase { |
- public: |
- explicit FakeImpl(const scoped_refptr<CastEnvironment>& cast_environment) |
- : ImplBase(cast_environment, transport::kFakeSoftwareVideo), |
- last_decoded_id_(-1) { |
- if (ImplBase::cast_initialization_status_ != STATUS_VIDEO_UNINITIALIZED) |
- return; |
- ImplBase::cast_initialization_status_ = STATUS_VIDEO_INITIALIZED; |
- } |
- |
- private: |
- virtual ~FakeImpl() {} |
- |
- virtual scoped_refptr<VideoFrame> Decode(uint8* data, int len) OVERRIDE { |
- base::JSONReader reader; |
- scoped_ptr<base::Value> values(reader.Read( |
- base::StringPiece(reinterpret_cast<char*>(data), len))); |
- base::DictionaryValue* dict = NULL; |
- values->GetAsDictionary(&dict); |
- |
- bool key = false; |
- int id = 0; |
- int ref = 0; |
- dict->GetBoolean("key", &key); |
- dict->GetInteger("id", &id); |
- dict->GetInteger("ref", &ref); |
- DCHECK(id == last_decoded_id_ + 1); |
- last_decoded_id_ = id; |
- return media::VideoFrame::CreateBlackFrame(gfx::Size(2, 2)); |
- } |
- |
- int last_decoded_id_; |
- |
- DISALLOW_COPY_AND_ASSIGN(FakeImpl); |
-}; |
-#endif |
- |
-VideoDecoder::VideoDecoder( |
- const scoped_refptr<CastEnvironment>& cast_environment, |
- const FrameReceiverConfig& video_config) |
- : cast_environment_(cast_environment) { |
- switch (video_config.codec.video) { |
-#ifndef OFFICIAL_BUILD |
- case transport::kFakeSoftwareVideo: |
- impl_ = new FakeImpl(cast_environment); |
- break; |
-#endif |
- case transport::kVp8: |
- impl_ = new Vp8Impl(cast_environment); |
- break; |
- case transport::kH264: |
- // TODO(miu): Need implementation. |
- NOTIMPLEMENTED(); |
- break; |
- default: |
- NOTREACHED() << "Unknown or unspecified codec."; |
- break; |
- } |
-} |
- |
-VideoDecoder::~VideoDecoder() {} |
- |
-CastInitializationStatus VideoDecoder::InitializationResult() const { |
- if (impl_) |
- return impl_->InitializationResult(); |
- return STATUS_UNSUPPORTED_VIDEO_CODEC; |
-} |
- |
-void VideoDecoder::DecodeFrame( |
- scoped_ptr<transport::EncodedFrame> encoded_frame, |
- const DecodeFrameCallback& callback) { |
- DCHECK(encoded_frame.get()); |
- DCHECK(!callback.is_null()); |
- if (!impl_ || impl_->InitializationResult() != STATUS_VIDEO_INITIALIZED) { |
- callback.Run(make_scoped_refptr<VideoFrame>(NULL), false); |
- return; |
- } |
- cast_environment_->PostTask(CastEnvironment::VIDEO, |
- FROM_HERE, |
- base::Bind(&VideoDecoder::ImplBase::DecodeFrame, |
- impl_, |
- base::Passed(&encoded_frame), |
- callback)); |
-} |
- |
-} // namespace cast |
-} // namespace media |