| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "media/base/android/video_decoder_job.h" | |
| 6 | |
| 7 #include <utility> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/lazy_instance.h" | |
| 11 #include "base/threading/thread.h" | |
| 12 #include "media/base/android/media_drm_bridge.h" | |
| 13 #include "media/base/android/sdk_media_codec_bridge.h" | |
| 14 | |
| 15 namespace media { | |
| 16 | |
| 17 class VideoDecoderThread : public base::Thread { | |
| 18 public: | |
| 19 VideoDecoderThread() : base::Thread("MediaSource_VideoDecoderThread") { | |
| 20 Start(); | |
| 21 } | |
| 22 }; | |
| 23 | |
| 24 // TODO(qinmin): Check if it is tolerable to use worker pool to handle all the | |
| 25 // decoding tasks so that we don't need a global thread here. | |
| 26 // http://crbug.com/245750 | |
| 27 base::LazyInstance<VideoDecoderThread>::Leaky | |
| 28 g_video_decoder_thread = LAZY_INSTANCE_INITIALIZER; | |
| 29 | |
| 30 VideoDecoderJob::VideoDecoderJob( | |
| 31 const base::Closure& request_data_cb, | |
| 32 const base::Closure& on_demuxer_config_changed_cb) | |
| 33 : MediaDecoderJob(g_video_decoder_thread.Pointer()->task_runner(), | |
| 34 request_data_cb, | |
| 35 on_demuxer_config_changed_cb), | |
| 36 video_codec_(kUnknownVideoCodec), | |
| 37 config_width_(0), | |
| 38 config_height_(0), | |
| 39 output_width_(0), | |
| 40 output_height_(0) { | |
| 41 } | |
| 42 | |
| 43 VideoDecoderJob::~VideoDecoderJob() {} | |
| 44 | |
| 45 bool VideoDecoderJob::SetVideoSurface(gl::ScopedJavaSurface surface) { | |
| 46 // For an empty surface, always pass it to the |media_codec_bridge_| job so | |
| 47 // that it can detach from the current one. Otherwise, don't pass an | |
| 48 // unprotected surface if the video content requires a protected one. | |
| 49 if (!surface.IsEmpty() && IsProtectedSurfaceRequired() && | |
| 50 !surface.is_protected()) { | |
| 51 return false; | |
| 52 } | |
| 53 | |
| 54 surface_ = std::move(surface); | |
| 55 need_to_reconfig_decoder_job_ = true; | |
| 56 return true; | |
| 57 } | |
| 58 | |
| 59 bool VideoDecoderJob::HasStream() const { | |
| 60 return video_codec_ != kUnknownVideoCodec; | |
| 61 } | |
| 62 | |
| 63 void VideoDecoderJob::ReleaseDecoderResources() { | |
| 64 MediaDecoderJob::ReleaseDecoderResources(); | |
| 65 surface_ = gl::ScopedJavaSurface(); | |
| 66 } | |
| 67 | |
| 68 void VideoDecoderJob::SetDemuxerConfigs(const DemuxerConfigs& configs) { | |
| 69 video_codec_ = configs.video_codec; | |
| 70 config_width_ = configs.video_size.width(); | |
| 71 config_height_ = configs.video_size.height(); | |
| 72 set_is_content_encrypted(configs.is_video_encrypted); | |
| 73 if (!media_codec_bridge_) { | |
| 74 output_width_ = config_width_; | |
| 75 output_height_ = config_height_; | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 void VideoDecoderJob::ReleaseOutputBuffer( | |
| 80 int output_buffer_index, | |
| 81 size_t offset, | |
| 82 size_t size, | |
| 83 bool render_output, | |
| 84 bool is_late_frame, | |
| 85 base::TimeDelta current_presentation_timestamp, | |
| 86 MediaCodecStatus status, | |
| 87 const DecoderCallback& callback) { | |
| 88 media_codec_bridge_->ReleaseOutputBuffer(output_buffer_index, render_output); | |
| 89 callback.Run(status, is_late_frame, current_presentation_timestamp, | |
| 90 current_presentation_timestamp); | |
| 91 } | |
| 92 | |
| 93 bool VideoDecoderJob::ComputeTimeToRender() const { | |
| 94 return true; | |
| 95 } | |
| 96 | |
| 97 bool VideoDecoderJob::IsCodecReconfigureNeeded( | |
| 98 const DemuxerConfigs& configs) const { | |
| 99 if (!media_codec_bridge_) | |
| 100 return true; | |
| 101 | |
| 102 if (!AreDemuxerConfigsChanged(configs)) | |
| 103 return false; | |
| 104 | |
| 105 bool only_size_changed = false; | |
| 106 if (video_codec_ == configs.video_codec && | |
| 107 is_content_encrypted() == configs.is_video_encrypted) { | |
| 108 only_size_changed = true; | |
| 109 } | |
| 110 | |
| 111 return !only_size_changed || | |
| 112 !static_cast<VideoCodecBridge*>(media_codec_bridge_.get())-> | |
| 113 IsAdaptivePlaybackSupported(configs.video_size.width(), | |
| 114 configs.video_size.height()); | |
| 115 } | |
| 116 | |
| 117 bool VideoDecoderJob::AreDemuxerConfigsChanged( | |
| 118 const DemuxerConfigs& configs) const { | |
| 119 return video_codec_ != configs.video_codec || | |
| 120 is_content_encrypted() != configs.is_video_encrypted || | |
| 121 config_width_ != configs.video_size.width() || | |
| 122 config_height_ != configs.video_size.height(); | |
| 123 } | |
| 124 | |
| 125 MediaDecoderJob::MediaDecoderJobStatus | |
| 126 VideoDecoderJob::CreateMediaCodecBridgeInternal() { | |
| 127 if (surface_.IsEmpty()) { | |
| 128 ReleaseMediaCodecBridge(); | |
| 129 return STATUS_FAILURE; | |
| 130 } | |
| 131 | |
| 132 // If we cannot find a key frame in cache, browser seek is needed. | |
| 133 bool next_video_data_is_iframe = SetCurrentFrameToPreviouslyCachedKeyFrame(); | |
| 134 if (!next_video_data_is_iframe) | |
| 135 return STATUS_KEY_FRAME_REQUIRED; | |
| 136 | |
| 137 bool is_secure = is_content_encrypted() && drm_bridge() && | |
| 138 drm_bridge()->IsProtectedSurfaceRequired(); | |
| 139 | |
| 140 media_codec_bridge_.reset(VideoCodecBridge::CreateDecoder( | |
| 141 video_codec_, is_secure, gfx::Size(config_width_, config_height_), | |
| 142 surface_.j_surface().obj(), GetMediaCrypto())); | |
| 143 | |
| 144 if (!media_codec_bridge_) | |
| 145 return STATUS_FAILURE; | |
| 146 | |
| 147 return STATUS_SUCCESS; | |
| 148 } | |
| 149 | |
| 150 bool VideoDecoderJob::UpdateOutputFormat() { | |
| 151 if (!media_codec_bridge_) | |
| 152 return false; | |
| 153 int prev_output_width = output_width_; | |
| 154 int prev_output_height = output_height_; | |
| 155 // See b/18224769. The values reported from MediaCodecBridge::GetOutputSize | |
| 156 // correspond to the actual video frame size, but this is not necessarily the | |
| 157 // size that should be output. | |
| 158 output_width_ = config_width_; | |
| 159 output_height_ = config_height_; | |
| 160 return (output_width_ != prev_output_width) || | |
| 161 (output_height_ != prev_output_height); | |
| 162 } | |
| 163 | |
| 164 bool VideoDecoderJob::IsProtectedSurfaceRequired() { | |
| 165 return is_content_encrypted() && drm_bridge() && | |
| 166 drm_bridge()->IsProtectedSurfaceRequired(); | |
| 167 } | |
| 168 | |
| 169 } // namespace media | |
| OLD | NEW |