1eb3723c5ba90a9e40418dd54f5649ca6c83a173
[platform/framework/web/crosswalk.git] / src / media / base / android / video_decoder_job.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/base/android/video_decoder_job.h"
6
7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
9 #include "base/threading/thread.h"
10 #include "media/base/android/media_codec_bridge.h"
11 #include "media/base/android/media_drm_bridge.h"
12
13 namespace media {
14
15 class VideoDecoderThread : public base::Thread {
16  public:
17   VideoDecoderThread() : base::Thread("MediaSource_VideoDecoderThread") {
18     Start();
19   }
20 };
21
22 // TODO(qinmin): Check if it is tolerable to use worker pool to handle all the
23 // decoding tasks so that we don't need a global thread here.
24 // http://crbug.com/245750
25 base::LazyInstance<VideoDecoderThread>::Leaky
26     g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER;
27
28 VideoDecoderJob::VideoDecoderJob(
29     const base::Closure& request_data_cb,
30     const base::Closure& request_resources_cb,
31     const base::Closure& on_demuxer_config_changed_cb)
32     : MediaDecoderJob(g_video_decoder_thread.Pointer()->message_loop_proxy(),
33                       request_data_cb,
34                       on_demuxer_config_changed_cb),
35       video_codec_(kUnknownVideoCodec),
36       width_(0),
37       height_(0),
38       request_resources_cb_(request_resources_cb),
39       next_video_data_is_iframe_(true) {
40 }
41
42 VideoDecoderJob::~VideoDecoderJob() {}
43
44 bool VideoDecoderJob::SetVideoSurface(gfx::ScopedJavaSurface surface) {
45   // For an empty surface, always pass it to the |media_codec_bridge_| job so
46   // that it can detach from the current one. Otherwise, don't pass an
47   // unprotected surface if the video content requires a protected one.
48   if (!surface.IsEmpty() && IsProtectedSurfaceRequired() &&
49       !surface.is_protected()) {
50     return false;
51   }
52
53   surface_ =  surface.Pass();
54   need_to_reconfig_decoder_job_ = true;
55   return true;
56 }
57
58 bool VideoDecoderJob::HasStream() const {
59   return video_codec_ != kUnknownVideoCodec;
60 }
61
62 void VideoDecoderJob::Flush() {
63   MediaDecoderJob::Flush();
64   next_video_data_is_iframe_ = true;
65 }
66
67 void VideoDecoderJob::ReleaseDecoderResources() {
68   MediaDecoderJob::ReleaseDecoderResources();
69   surface_ = gfx::ScopedJavaSurface();
70 }
71
72 void VideoDecoderJob::ReleaseOutputBuffer(
73     int output_buffer_index,
74     size_t size,
75     bool render_output,
76     base::TimeDelta current_presentation_timestamp,
77     const ReleaseOutputCompletionCallback& callback) {
78   media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, render_output);
79   callback.Run(current_presentation_timestamp, current_presentation_timestamp);
80 }
81
82 bool VideoDecoderJob::ComputeTimeToRender() const {
83   return true;
84 }
85
86 void VideoDecoderJob::UpdateDemuxerConfigs(const DemuxerConfigs& configs) {
87   video_codec_ = configs.video_codec;
88   width_ = configs.video_size.width();
89   height_ = configs.video_size.height();
90   set_is_content_encrypted(configs.is_video_encrypted);
91 }
92
93 bool VideoDecoderJob::IsCodecReconfigureNeeded(
94     const DemuxerConfigs& configs) const {
95   if (!media_codec_bridge_)
96     return true;
97
98   if (!AreDemuxerConfigsChanged(configs))
99     return false;
100
101   bool only_size_changed = false;
102   if (video_codec_ == configs.video_codec &&
103       is_content_encrypted() == configs.is_video_encrypted) {
104     only_size_changed = true;
105   }
106
107   return !only_size_changed ||
108       !static_cast<VideoCodecBridge*>(media_codec_bridge_.get())->
109           IsAdaptivePlaybackSupported(configs.video_size.width(),
110                                       configs.video_size.height());
111 }
112
113 bool VideoDecoderJob::AreDemuxerConfigsChanged(
114     const DemuxerConfigs& configs) const {
115   return video_codec_ != configs.video_codec ||
116       is_content_encrypted() != configs.is_video_encrypted ||
117       width_ != configs.video_size.width() ||
118       height_ != configs.video_size.height();
119 }
120
121 bool VideoDecoderJob::CreateMediaCodecBridgeInternal() {
122   if (surface_.IsEmpty()) {
123     ReleaseMediaCodecBridge();
124     return false;
125   }
126
127   // If the next data is not iframe, return false so that the player need to
128   // perform a browser seek.
129   if (!next_video_data_is_iframe_)
130     return false;
131
132   bool is_secure = is_content_encrypted() && drm_bridge() &&
133       drm_bridge()->IsProtectedSurfaceRequired();
134
135   media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder(
136       video_codec_, is_secure, gfx::Size(width_, height_),
137       surface_.j_surface().obj(), GetMediaCrypto().obj()));
138
139   if (!media_codec_bridge_)
140     return false;
141
142   request_resources_cb_.Run();
143   return true;
144 }
145
146 void VideoDecoderJob::CurrentDataConsumed(bool is_config_change) {
147   next_video_data_is_iframe_ = is_config_change;
148 }
149
150 bool VideoDecoderJob::IsProtectedSurfaceRequired() {
151   return is_content_encrypted() && drm_bridge() &&
152       drm_bridge()->IsProtectedSurfaceRequired();
153 }
154
155 }  // namespace media