Chromium Code Reviews| Index: media/base/android/video_decoder_job.cc |
| diff --git a/media/base/android/video_decoder_job.cc b/media/base/android/video_decoder_job.cc |
| index 884bc6d3d0ba6247073c9adb355783cf90576a0e..649f81d06a32f2e23107afb8507314ec87bf704f 100644 |
| --- a/media/base/android/video_decoder_job.cc |
| +++ b/media/base/android/video_decoder_job.cc |
| @@ -8,6 +8,7 @@ |
| #include "base/lazy_instance.h" |
| #include "base/threading/thread.h" |
| #include "media/base/android/media_codec_bridge.h" |
| +#include "media/base/android/media_drm_bridge.h" |
| namespace media { |
| @@ -24,39 +25,50 @@ class VideoDecoderThread : public base::Thread { |
| base::LazyInstance<VideoDecoderThread>::Leaky |
| g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER; |
| -VideoDecoderJob* VideoDecoderJob::Create( |
| - const VideoCodec video_codec, |
| - bool is_secure, |
| - const gfx::Size& size, |
| - jobject surface, |
| - jobject media_crypto, |
| - const base::Closure& request_data_cb, |
| - const base::Closure& request_resources_cb, |
| - const base::Closure& release_resources_cb) { |
| - scoped_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( |
| - video_codec, is_secure, size, surface, media_crypto)); |
| - if (codec) |
| - return new VideoDecoderJob(codec.Pass(), request_data_cb, |
| - request_resources_cb, release_resources_cb); |
| - |
| - LOG(ERROR) << "Failed to create VideoDecoderJob."; |
| - return NULL; |
| -} |
| - |
| VideoDecoderJob::VideoDecoderJob( |
| - scoped_ptr<VideoCodecBridge> video_codec_bridge, |
| const base::Closure& request_data_cb, |
| const base::Closure& request_resources_cb, |
| - const base::Closure& release_resources_cb) |
| + const base::Closure& release_resources_cb, |
| + const base::Closure& on_demuxer_config_changed_cb) |
| : MediaDecoderJob(g_video_decoder_thread.Pointer()->message_loop_proxy(), |
| - video_codec_bridge.get(), request_data_cb), |
| - video_codec_bridge_(video_codec_bridge.Pass()), |
| - release_resources_cb_(release_resources_cb) { |
| - request_resources_cb.Run(); |
| + request_data_cb, |
| + on_demuxer_config_changed_cb), |
| + video_codec_(kUnknownVideoCodec), |
| + width_(0), |
| + height_(0), |
| + request_resources_cb_(request_resources_cb), |
| + release_resources_cb_(release_resources_cb), |
| + next_video_data_is_iframe_(true) { |
| } |
| -VideoDecoderJob::~VideoDecoderJob() { |
| - release_resources_cb_.Run(); |
| +VideoDecoderJob::~VideoDecoderJob() {} |
| + |
| +bool VideoDecoderJob::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
| + // For an empty surface, always pass it to the decoder job so that it |
|
wolenetz
2014/05/21 00:48:04
nit: pass to decoder job? we are the decoder job.
qinmin
2014/05/22 00:35:55
Fixed, should be |media_codec_bridge_|.
On 2014/05
|
| + // can detach from the current one. Otherwise, don't pass an unprotected |
| + // surface if the video content requires a protected one. |
| + if (!surface.IsEmpty() && IsProtectedSurfaceRequired() && |
| + !surface.is_protected()) { |
| + return false; |
| + } |
| + |
| + surface_ = surface.Pass(); |
| + need_to_reconfig_decoder_job_ = true; |
| + return true; |
| +} |
| + |
| +bool VideoDecoderJob::HasStream() const { |
| + return video_codec_ != kUnknownVideoCodec; |
| +} |
| + |
| +void VideoDecoderJob::Flush() { |
| + MediaDecoderJob::Flush(); |
| + next_video_data_is_iframe_ = true; |
| +} |
| + |
| +void VideoDecoderJob::ReleaseDecoderResources() { |
| + MediaDecoderJob::ReleaseDecoderResources(); |
| + surface_ = gfx::ScopedJavaSurface(); |
| } |
| void VideoDecoderJob::ReleaseOutputBuffer( |
| @@ -65,7 +77,7 @@ void VideoDecoderJob::ReleaseOutputBuffer( |
| bool render_output, |
| base::TimeDelta current_presentation_timestamp, |
| const ReleaseOutputCompletionCallback& callback) { |
| - video_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, render_output); |
| + media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, render_output); |
| callback.Run(current_presentation_timestamp, current_presentation_timestamp); |
| } |
| @@ -73,4 +85,57 @@ bool VideoDecoderJob::ComputeTimeToRender() const { |
| return true; |
| } |
| +void VideoDecoderJob::UpdateDemuxerConfigs(const DemuxerConfigs& configs) { |
| + video_codec_ = configs.video_codec; |
| + width_ = configs.video_size.width(); |
| + height_ = configs.video_size.height(); |
| + set_is_content_encrypted(configs.is_video_encrypted); |
| +} |
| + |
| +bool VideoDecoderJob::IsDemuxerConfigChanged( |
| + const DemuxerConfigs& configs) const { |
| + return video_codec_ != configs.video_codec || |
| + is_content_encrypted() != configs.is_video_encrypted || |
| + width_ != configs.video_size.width() || |
| + height_ != configs.video_size.height(); |
| +} |
| + |
| +bool VideoDecoderJob::CreateMediaCodecBridgeInternal() { |
| + if (surface_.IsEmpty()) { |
| + ReleaseMediaCodecBridge(); |
| + return false; |
| + } |
| + |
| + // If the next data is not iframe, return false so that the player need to |
| + // perform a browser seek. |
| + if (!next_video_data_is_iframe_) |
| + return false; |
| + |
| + bool is_secure = is_content_encrypted() && drm_bridge() && |
| + drm_bridge()->IsProtectedSurfaceRequired(); |
| + |
| + media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder( |
| + video_codec_, is_secure, gfx::Size(width_, height_), |
| + surface_.j_surface().obj(), GetMediaCrypto().obj())); |
| + |
| + if (!media_codec_bridge_) |
| + return false; |
| + |
| + request_resources_cb_.Run(); |
| + return true; |
| +} |
| + |
| +void VideoDecoderJob::CurrentDataConsumed(bool is_config_change) { |
| + next_video_data_is_iframe_ = is_config_change; |
| +} |
| + |
| +void VideoDecoderJob::OnMediaCodecBridgeReleased() { |
| + release_resources_cb_.Run(); |
| +} |
| + |
| +bool VideoDecoderJob::IsProtectedSurfaceRequired() { |
| + return is_content_encrypted() && drm_bridge() && |
| + drm_bridge()->IsProtectedSurfaceRequired(); |
| +} |
| + |
| } // namespace media |