| 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
|
| + // 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
|
|
|