| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/android/video_decoder_job.h" | 5 #include "media/base/android/video_decoder_job.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
| 9 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
| 10 #include "media/base/android/media_codec_bridge.h" | 10 #include "media/base/android/media_codec_bridge.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER; | 26 g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER; |
| 27 | 27 |
| 28 VideoDecoderJob::VideoDecoderJob( | 28 VideoDecoderJob::VideoDecoderJob( |
| 29 const base::Closure& request_data_cb, | 29 const base::Closure& request_data_cb, |
| 30 const base::Closure& request_resources_cb, | 30 const base::Closure& request_resources_cb, |
| 31 const base::Closure& on_demuxer_config_changed_cb) | 31 const base::Closure& on_demuxer_config_changed_cb) |
| 32 : MediaDecoderJob(g_video_decoder_thread.Pointer()->message_loop_proxy(), | 32 : MediaDecoderJob(g_video_decoder_thread.Pointer()->message_loop_proxy(), |
| 33 request_data_cb, | 33 request_data_cb, |
| 34 on_demuxer_config_changed_cb), | 34 on_demuxer_config_changed_cb), |
| 35 video_codec_(kUnknownVideoCodec), | 35 video_codec_(kUnknownVideoCodec), |
| 36 width_(0), | 36 config_width_(0), |
| 37 height_(0), | 37 config_height_(0), |
| 38 output_width_(0), |
| 39 output_height_(0), |
| 38 request_resources_cb_(request_resources_cb), | 40 request_resources_cb_(request_resources_cb), |
| 39 next_video_data_is_iframe_(true) { | 41 next_video_data_is_iframe_(true) { |
| 40 } | 42 } |
| 41 | 43 |
| 42 VideoDecoderJob::~VideoDecoderJob() {} | 44 VideoDecoderJob::~VideoDecoderJob() {} |
| 43 | 45 |
| 44 bool VideoDecoderJob::SetVideoSurface(gfx::ScopedJavaSurface surface) { | 46 bool VideoDecoderJob::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
| 45 // For an empty surface, always pass it to the |media_codec_bridge_| job so | 47 // 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 | 48 // that it can detach from the current one. Otherwise, don't pass an |
| 47 // unprotected surface if the video content requires a protected one. | 49 // unprotected surface if the video content requires a protected one. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 62 void VideoDecoderJob::Flush() { | 64 void VideoDecoderJob::Flush() { |
| 63 MediaDecoderJob::Flush(); | 65 MediaDecoderJob::Flush(); |
| 64 next_video_data_is_iframe_ = true; | 66 next_video_data_is_iframe_ = true; |
| 65 } | 67 } |
| 66 | 68 |
| 67 void VideoDecoderJob::ReleaseDecoderResources() { | 69 void VideoDecoderJob::ReleaseDecoderResources() { |
| 68 MediaDecoderJob::ReleaseDecoderResources(); | 70 MediaDecoderJob::ReleaseDecoderResources(); |
| 69 surface_ = gfx::ScopedJavaSurface(); | 71 surface_ = gfx::ScopedJavaSurface(); |
| 70 } | 72 } |
| 71 | 73 |
| 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_; |
| 82 } |
| 83 } |
| 84 |
| 72 void VideoDecoderJob::ReleaseOutputBuffer( | 85 void VideoDecoderJob::ReleaseOutputBuffer( |
| 73 int output_buffer_index, | 86 int output_buffer_index, |
| 74 size_t size, | 87 size_t size, |
| 75 bool render_output, | 88 bool render_output, |
| 76 base::TimeDelta current_presentation_timestamp, | 89 base::TimeDelta current_presentation_timestamp, |
| 77 const ReleaseOutputCompletionCallback& callback) { | 90 const ReleaseOutputCompletionCallback& callback) { |
| 78 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, render_output); | 91 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, render_output); |
| 79 callback.Run(current_presentation_timestamp, current_presentation_timestamp); | 92 callback.Run(current_presentation_timestamp, current_presentation_timestamp); |
| 80 } | 93 } |
| 81 | 94 |
| 82 bool VideoDecoderJob::ComputeTimeToRender() const { | 95 bool VideoDecoderJob::ComputeTimeToRender() const { |
| 83 return true; | 96 return true; |
| 84 } | 97 } |
| 85 | 98 |
| 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( | 99 bool VideoDecoderJob::IsCodecReconfigureNeeded( |
| 94 const DemuxerConfigs& configs) const { | 100 const DemuxerConfigs& configs) const { |
| 95 if (!media_codec_bridge_) | 101 if (!media_codec_bridge_) |
| 96 return true; | 102 return true; |
| 97 | 103 |
| 98 if (!AreDemuxerConfigsChanged(configs)) | 104 if (!AreDemuxerConfigsChanged(configs)) |
| 99 return false; | 105 return false; |
| 100 | 106 |
| 101 bool only_size_changed = false; | 107 bool only_size_changed = false; |
| 102 if (video_codec_ == configs.video_codec && | 108 if (video_codec_ == configs.video_codec && |
| 103 is_content_encrypted() == configs.is_video_encrypted) { | 109 is_content_encrypted() == configs.is_video_encrypted) { |
| 104 only_size_changed = true; | 110 only_size_changed = true; |
| 105 } | 111 } |
| 106 | 112 |
| 107 return !only_size_changed || | 113 return !only_size_changed || |
| 108 !static_cast<VideoCodecBridge*>(media_codec_bridge_.get())-> | 114 !static_cast<VideoCodecBridge*>(media_codec_bridge_.get())-> |
| 109 IsAdaptivePlaybackSupported(configs.video_size.width(), | 115 IsAdaptivePlaybackSupported(configs.video_size.width(), |
| 110 configs.video_size.height()); | 116 configs.video_size.height()); |
| 111 } | 117 } |
| 112 | 118 |
| 113 bool VideoDecoderJob::AreDemuxerConfigsChanged( | 119 bool VideoDecoderJob::AreDemuxerConfigsChanged( |
| 114 const DemuxerConfigs& configs) const { | 120 const DemuxerConfigs& configs) const { |
| 115 return video_codec_ != configs.video_codec || | 121 return video_codec_ != configs.video_codec || |
| 116 is_content_encrypted() != configs.is_video_encrypted || | 122 is_content_encrypted() != configs.is_video_encrypted || |
| 117 width_ != configs.video_size.width() || | 123 config_width_ != configs.video_size.width() || |
| 118 height_ != configs.video_size.height(); | 124 config_height_ != configs.video_size.height(); |
| 119 } | 125 } |
| 120 | 126 |
| 121 bool VideoDecoderJob::CreateMediaCodecBridgeInternal() { | 127 bool VideoDecoderJob::CreateMediaCodecBridgeInternal() { |
| 122 if (surface_.IsEmpty()) { | 128 if (surface_.IsEmpty()) { |
| 123 ReleaseMediaCodecBridge(); | 129 ReleaseMediaCodecBridge(); |
| 124 return false; | 130 return false; |
| 125 } | 131 } |
| 126 | 132 |
| 127 // If the next data is not iframe, return false so that the player need to | 133 // If the next data is not iframe, return false so that the player need to |
| 128 // perform a browser seek. | 134 // perform a browser seek. |
| 129 if (!next_video_data_is_iframe_) | 135 if (!next_video_data_is_iframe_) |
| 130 return false; | 136 return false; |
| 131 | 137 |
| 132 bool is_secure = is_content_encrypted() && drm_bridge() && | 138 bool is_secure = is_content_encrypted() && drm_bridge() && |
| 133 drm_bridge()->IsProtectedSurfaceRequired(); | 139 drm_bridge()->IsProtectedSurfaceRequired(); |
| 134 | 140 |
| 135 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder( | 141 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder( |
| 136 video_codec_, is_secure, gfx::Size(width_, height_), | 142 video_codec_, is_secure, gfx::Size(config_width_, config_height_), |
| 137 surface_.j_surface().obj(), GetMediaCrypto().obj())); | 143 surface_.j_surface().obj(), GetMediaCrypto().obj())); |
| 138 | 144 |
| 139 if (!media_codec_bridge_) | 145 if (!media_codec_bridge_) |
| 140 return false; | 146 return false; |
| 141 | 147 |
| 142 request_resources_cb_.Run(); | 148 request_resources_cb_.Run(); |
| 143 return true; | 149 return true; |
| 144 } | 150 } |
| 145 | 151 |
| 146 void VideoDecoderJob::CurrentDataConsumed(bool is_config_change) { | 152 void VideoDecoderJob::CurrentDataConsumed(bool is_config_change) { |
| 147 next_video_data_is_iframe_ = is_config_change; | 153 next_video_data_is_iframe_ = is_config_change; |
| 148 } | 154 } |
| 149 | 155 |
| 156 bool VideoDecoderJob::UpdateOutputFormat() { |
| 157 if (!media_codec_bridge_) |
| 158 return false; |
| 159 int prev_output_width = output_width_; |
| 160 int prev_output_height = output_height_; |
| 161 media_codec_bridge_->GetOutputFormat(&output_width_, &output_height_); |
| 162 return (output_width_ != prev_output_width) || |
| 163 (output_height_ != prev_output_height); |
| 164 } |
| 165 |
| 150 bool VideoDecoderJob::IsProtectedSurfaceRequired() { | 166 bool VideoDecoderJob::IsProtectedSurfaceRequired() { |
| 151 return is_content_encrypted() && drm_bridge() && | 167 return is_content_encrypted() && drm_bridge() && |
| 152 drm_bridge()->IsProtectedSurfaceRequired(); | 168 drm_bridge()->IsProtectedSurfaceRequired(); |
| 153 } | 169 } |
| 154 | 170 |
| 155 } // namespace media | 171 } // namespace media |
| OLD | NEW |