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..e69187dba6d566c9b77bee3f06d57bcfb8fbf390 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 |media_codec_bridge_| 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 |