146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// found in the LICENSE file.
468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "media/cast/receiver/video_decoder.h"
668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/bind.h"
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/bind_helpers.h"
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/json/json_reader.h"
10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/location.h"
1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/logging.h"
120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/values.h"
13c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "media/base/video_util.h"
14c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "media/cast/cast_defines.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "media/cast/cast_environment.h"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// backwards compatibility for legacy applications using the library.
18c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#define VPX_CODEC_DISABLE_COMPAT 1
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
20c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h"
21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "ui/gfx/size.h"
2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace media {
2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)namespace cast {
2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// Base class that handles the common problem of detecting dropped frames, and
27c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// then invoking the Decode() method implemented by the subclasses to convert
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// the encoded payload data into a usable video frame.
29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass VideoDecoder::ImplBase
30c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : public base::RefCountedThreadSafe<VideoDecoder::ImplBase> {
31c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
32c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ImplBase(const scoped_refptr<CastEnvironment>& cast_environment,
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           Codec codec)
34c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      : cast_environment_(cast_environment),
35c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        codec_(codec),
36c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        cast_initialization_status_(STATUS_VIDEO_UNINITIALIZED),
37c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        seen_first_frame_(false) {}
38c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
39c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CastInitializationStatus InitializationResult() const {
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return cast_initialization_status_;
41c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
42c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void DecodeFrame(scoped_ptr<EncodedFrame> encoded_frame,
44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   const DecodeFrameCallback& callback) {
45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK_EQ(cast_initialization_status_, STATUS_VIDEO_INITIALIZED);
46c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
47c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    COMPILE_ASSERT(sizeof(encoded_frame->frame_id) == sizeof(last_frame_id_),
48c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                   size_of_frame_id_types_do_not_match);
49c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    bool is_continuous = true;
50c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (seen_first_frame_) {
51c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      const uint32 frames_ahead = encoded_frame->frame_id - last_frame_id_;
52c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      if (frames_ahead > 1) {
53c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        RecoverBecauseFramesWereDropped();
54c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        is_continuous = false;
55c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      }
56c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    } else {
57c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      seen_first_frame_ = true;
58c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
59c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    last_frame_id_ = encoded_frame->frame_id;
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const scoped_refptr<VideoFrame> decoded_frame = Decode(
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        encoded_frame->mutable_bytes(),
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        static_cast<int>(encoded_frame->data.size()));
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cast_environment_->PostTask(
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        CastEnvironment::MAIN,
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        FROM_HERE,
67c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        base::Bind(callback, decoded_frame, is_continuous));
68c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
69c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
70c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch protected:
71c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  friend class base::RefCountedThreadSafe<ImplBase>;
72c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual ~ImplBase() {}
73c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
74c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual void RecoverBecauseFramesWereDropped() {}
75c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
76c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Note: Implementation of Decode() is allowed to mutate |data|.
77c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual scoped_refptr<VideoFrame> Decode(uint8* data, int len) = 0;
78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const scoped_refptr<CastEnvironment> cast_environment_;
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const Codec codec_;
81c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Subclass' ctor is expected to set this to STATUS_VIDEO_INITIALIZED.
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  CastInitializationStatus cast_initialization_status_;
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  bool seen_first_frame_;
87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  uint32 last_frame_id_;
88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ImplBase);
90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass VideoDecoder::Vp8Impl : public VideoDecoder::ImplBase {
93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch public:
94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  explicit Vp8Impl(const scoped_refptr<CastEnvironment>& cast_environment)
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : ImplBase(cast_environment, CODEC_VIDEO_VP8) {
96c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (ImplBase::cast_initialization_status_ != STATUS_VIDEO_UNINITIALIZED)
97c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return;
98c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    vpx_codec_dec_cfg_t cfg = {0};
100c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // TODO(miu): Revisit this for typical multi-core desktop use case.  This
101c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // feels like it should be 4 or 8.
102c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    cfg.threads = 1;
103c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
104c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK(vpx_codec_get_caps(vpx_codec_vp8_dx()) & VPX_CODEC_CAP_POSTPROC);
105c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (vpx_codec_dec_init(&context_,
106c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           vpx_codec_vp8_dx(),
107c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           &cfg,
108c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                           VPX_CODEC_USE_POSTPROC) != VPX_CODEC_OK) {
109c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      ImplBase::cast_initialization_status_ =
110c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          STATUS_INVALID_VIDEO_CONFIGURATION;
111c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return;
112c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
113c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ImplBase::cast_initialization_status_ = STATUS_VIDEO_INITIALIZED;
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch private:
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual ~Vp8Impl() {
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (ImplBase::cast_initialization_status_ == STATUS_VIDEO_INITIALIZED)
119c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      CHECK_EQ(VPX_CODEC_OK, vpx_codec_destroy(&context_));
120c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  virtual scoped_refptr<VideoFrame> Decode(uint8* data, int len) OVERRIDE {
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (len <= 0 || vpx_codec_decode(&context_,
124c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     data,
125c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     static_cast<unsigned int>(len),
126c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     NULL,
127c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                     0) != VPX_CODEC_OK) {
128c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return NULL;
129c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
130c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    vpx_codec_iter_t iter = NULL;
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    vpx_image_t* const image = vpx_codec_get_frame(&context_, &iter);
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (!image)
134c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return NULL;
135c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    if (image->fmt != VPX_IMG_FMT_I420 && image->fmt != VPX_IMG_FMT_YV12) {
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NOTREACHED();
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      return NULL;
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
139c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    DCHECK(vpx_codec_get_frame(&context_, &iter) == NULL)
140c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        << "Should have only decoded exactly one frame.";
141c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
142c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const gfx::Size frame_size(image->d_w, image->d_h);
143c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Note: Timestamp for the VideoFrame will be set in VideoReceiver.
144c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const scoped_refptr<VideoFrame> decoded_frame =
145c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        VideoFrame::CreateFrame(VideoFrame::YV12,
146c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                frame_size,
147c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                gfx::Rect(frame_size),
148c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                frame_size,
149c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                base::TimeDelta());
150c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    CopyYPlane(image->planes[VPX_PLANE_Y],
151c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               image->stride[VPX_PLANE_Y],
152c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               image->d_h,
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               decoded_frame.get());
154c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    CopyUPlane(image->planes[VPX_PLANE_U],
155c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               image->stride[VPX_PLANE_U],
156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               (image->d_h + 1) / 2,
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               decoded_frame.get());
158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    CopyVPlane(image->planes[VPX_PLANE_V],
159c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               image->stride[VPX_PLANE_V],
160c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch               (image->d_h + 1) / 2,
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci               decoded_frame.get());
162c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return decoded_frame;
163c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
164c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // VPX decoder context (i.e., an instantiation).
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  vpx_codec_ctx_t context_;
167c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
168c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DISALLOW_COPY_AND_ASSIGN(Vp8Impl);
169c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch};
170c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#ifndef OFFICIAL_BUILD
1720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// A fake video decoder that always output 2x2 black frames.
1730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass VideoDecoder::FakeImpl : public VideoDecoder::ImplBase {
1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch public:
1750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  explicit FakeImpl(const scoped_refptr<CastEnvironment>& cast_environment)
176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      : ImplBase(cast_environment, CODEC_VIDEO_FAKE),
1770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        last_decoded_id_(-1) {
1780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (ImplBase::cast_initialization_status_ != STATUS_VIDEO_UNINITIALIZED)
1790529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      return;
1800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    ImplBase::cast_initialization_status_ = STATUS_VIDEO_INITIALIZED;
1810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
1820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1830529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch private:
1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual ~FakeImpl() {}
1850529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual scoped_refptr<VideoFrame> Decode(uint8* data, int len) OVERRIDE {
187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Make sure this is a JSON string.
188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!len || data[0] != '{')
189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return NULL;
1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::JSONReader reader;
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<base::Value> values(
192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        reader.Read(base::StringPiece(reinterpret_cast<char*>(data), len)));
193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (!values)
194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      return NULL;
1950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    base::DictionaryValue* dict = NULL;
1960529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    values->GetAsDictionary(&dict);
1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
1980529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    bool key = false;
1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int id = 0;
2000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    int ref = 0;
2010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    dict->GetBoolean("key", &key);
2020529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    dict->GetInteger("id", &id);
2030529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    dict->GetInteger("ref", &ref);
2040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    DCHECK(id == last_decoded_id_ + 1);
2050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    last_decoded_id_ = id;
2060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return media::VideoFrame::CreateBlackFrame(gfx::Size(2, 2));
2070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  int last_decoded_id_;
2100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
2110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(FakeImpl);
2120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch};
2130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif
2140529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
215c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochVideoDecoder::VideoDecoder(
216c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const scoped_refptr<CastEnvironment>& cast_environment,
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    Codec codec)
218c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    : cast_environment_(cast_environment) {
21946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  switch (codec) {
2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#ifndef OFFICIAL_BUILD
221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case CODEC_VIDEO_FAKE:
2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      impl_ = new FakeImpl(cast_environment);
2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      break;
2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#endif
225116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case CODEC_VIDEO_VP8:
226c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      impl_ = new Vp8Impl(cast_environment);
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
228116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    case CODEC_VIDEO_H264:
229c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      // TODO(miu): Need implementation.
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      NOTIMPLEMENTED();
23168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      break;
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    default:
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      NOTREACHED() << "Unknown or unspecified codec.";
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      break;
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)VideoDecoder::~VideoDecoder() {}
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochCastInitializationStatus VideoDecoder::InitializationResult() const {
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (impl_.get())
242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return impl_->InitializationResult();
243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return STATUS_UNSUPPORTED_VIDEO_CODEC;
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid VideoDecoder::DecodeFrame(
247116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    scoped_ptr<EncodedFrame> encoded_frame,
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const DecodeFrameCallback& callback) {
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(encoded_frame.get());
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(!callback.is_null());
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!impl_.get() ||
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      impl_->InitializationResult() != STATUS_VIDEO_INITIALIZED) {
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    callback.Run(make_scoped_refptr<VideoFrame>(NULL), false);
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  cast_environment_->PostTask(CastEnvironment::VIDEO,
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              FROM_HERE,
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                              base::Bind(&VideoDecoder::ImplBase::DecodeFrame,
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                         impl_,
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                         base::Passed(&encoded_frame),
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                         callback));
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace cast
26568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}  // namespace media
266