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.
5 #include "media/base/android/video_decoder_job.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"
15 class VideoDecoderThread
: public base::Thread
{
17 VideoDecoderThread() : base::Thread("MediaSource_VideoDecoderThread") {
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
;
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(),
34 on_demuxer_config_changed_cb
),
35 video_codec_(kUnknownVideoCodec
),
40 request_resources_cb_(request_resources_cb
),
41 next_video_data_is_iframe_(true) {
44 VideoDecoderJob::~VideoDecoderJob() {}
46 bool VideoDecoderJob::SetVideoSurface(gfx::ScopedJavaSurface surface
) {
47 // For an empty surface, always pass it to the |media_codec_bridge_| job so
48 // that it can detach from the current one. Otherwise, don't pass an
49 // unprotected surface if the video content requires a protected one.
50 if (!surface
.IsEmpty() && IsProtectedSurfaceRequired() &&
51 !surface
.is_protected()) {
55 surface_
= surface
.Pass();
56 need_to_reconfig_decoder_job_
= true;
60 bool VideoDecoderJob::HasStream() const {
61 return video_codec_
!= kUnknownVideoCodec
;
64 void VideoDecoderJob::Flush() {
65 MediaDecoderJob::Flush();
66 next_video_data_is_iframe_
= true;
69 void VideoDecoderJob::ReleaseDecoderResources() {
70 MediaDecoderJob::ReleaseDecoderResources();
71 surface_
= gfx::ScopedJavaSurface();
74 void VideoDecoderJob::SetDemuxerConfigs(const DemuxerConfigs
& configs
) {
75 video_codec_
= configs
.video_codec
;
76 config_width_
= configs
.video_size
.width();
77 config_height_
= configs
.video_size
.height();
78 set_is_content_encrypted(configs
.is_video_encrypted
);
79 if (!media_codec_bridge_
) {
80 output_width_
= config_width_
;
81 output_height_
= config_height_
;
85 void VideoDecoderJob::ReleaseOutputBuffer(
86 int output_buffer_index
,
89 base::TimeDelta current_presentation_timestamp
,
90 const ReleaseOutputCompletionCallback
& callback
) {
91 media_codec_bridge_
->ReleaseOutputBuffer(output_buffer_index
, render_output
);
92 callback
.Run(current_presentation_timestamp
, current_presentation_timestamp
);
95 bool VideoDecoderJob::ComputeTimeToRender() const {
99 bool VideoDecoderJob::IsCodecReconfigureNeeded(
100 const DemuxerConfigs
& configs
) const {
101 if (!media_codec_bridge_
)
104 if (!AreDemuxerConfigsChanged(configs
))
107 bool only_size_changed
= false;
108 if (video_codec_
== configs
.video_codec
&&
109 is_content_encrypted() == configs
.is_video_encrypted
) {
110 only_size_changed
= true;
113 return !only_size_changed
||
114 !static_cast<VideoCodecBridge
*>(media_codec_bridge_
.get())->
115 IsAdaptivePlaybackSupported(configs
.video_size
.width(),
116 configs
.video_size
.height());
119 bool VideoDecoderJob::AreDemuxerConfigsChanged(
120 const DemuxerConfigs
& configs
) const {
121 return video_codec_
!= configs
.video_codec
||
122 is_content_encrypted() != configs
.is_video_encrypted
||
123 config_width_
!= configs
.video_size
.width() ||
124 config_height_
!= configs
.video_size
.height();
127 bool VideoDecoderJob::CreateMediaCodecBridgeInternal() {
128 if (surface_
.IsEmpty()) {
129 ReleaseMediaCodecBridge();
133 // If the next data is not iframe, return false so that the player need to
134 // perform a browser seek.
135 if (!next_video_data_is_iframe_
)
138 bool is_secure
= is_content_encrypted() && drm_bridge() &&
139 drm_bridge()->IsProtectedSurfaceRequired();
141 media_codec_bridge_
.reset(VideoCodecBridge::CreateDecoder(
142 video_codec_
, is_secure
, gfx::Size(config_width_
, config_height_
),
143 surface_
.j_surface().obj(), GetMediaCrypto().obj()));
145 if (!media_codec_bridge_
)
148 request_resources_cb_
.Run();
152 void VideoDecoderJob::CurrentDataConsumed(bool is_config_change
) {
153 next_video_data_is_iframe_
= is_config_change
;
156 bool VideoDecoderJob::UpdateOutputFormat() {
157 if (!media_codec_bridge_
)
159 int prev_output_width
= output_width_
;
160 int prev_output_height
= output_height_
;
161 // See b/18224769. The values reported from MediaCodecBridge::GetOutputFormat
162 // correspond to the actual video frame size, but this is not necessarily the
163 // size that should be output.
164 output_width_
= config_width_
;
165 output_height_
= config_height_
;
166 return (output_width_
!= prev_output_width
) ||
167 (output_height_
!= prev_output_height
);
170 bool VideoDecoderJob::IsProtectedSurfaceRequired() {
171 return is_content_encrypted() && drm_bridge() &&
172 drm_bridge()->IsProtectedSurfaceRequired();