| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/filters/omx_video_decoder.h" | 5 #include "media/filters/omx_video_decoder.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "media/base/callback.h" | 9 #include "media/base/callback.h" |
| 10 #include "media/base/filter_host.h" | 10 #include "media/base/filter_host.h" |
| 11 #include "media/base/limits.h" | 11 #include "media/base/limits.h" |
| 12 #include "media/ffmpeg/ffmpeg_common.h" | 12 #include "media/ffmpeg/ffmpeg_common.h" |
| 13 #include "media/filters/ffmpeg_interfaces.h" | 13 #include "media/filters/ffmpeg_interfaces.h" |
| 14 #include "media/video/omx_video_decode_engine.h" | 14 #include "media/video/omx_video_decode_engine.h" |
| 15 | 15 |
| 16 namespace media { | 16 namespace media { |
| 17 | 17 |
| 18 OmxVideoDecoder::OmxVideoDecoder( | 18 OmxVideoDecoder::OmxVideoDecoder( |
| 19 MessageLoop* message_loop, |
| 19 VideoDecodeContext* context) | 20 VideoDecodeContext* context) |
| 20 : decode_engine_(new OmxVideoDecodeEngine()), | 21 : message_loop_(message_loop), |
| 22 decode_engine_(new OmxVideoDecodeEngine()), |
| 21 decode_context_(context), | 23 decode_context_(context), |
| 22 width_(0), height_(0) { | 24 width_(0), height_(0) { |
| 23 DCHECK(decode_engine_.get()); | 25 DCHECK(decode_engine_.get()); |
| 24 memset(&info_, 0, sizeof(info_)); | 26 memset(&info_, 0, sizeof(info_)); |
| 25 } | 27 } |
| 26 | 28 |
| 27 OmxVideoDecoder::~OmxVideoDecoder() { | 29 OmxVideoDecoder::~OmxVideoDecoder() { |
| 28 // TODO(hclam): Make sure OmxVideoDecodeEngine is stopped. | 30 // TODO(hclam): Make sure OmxVideoDecodeEngine is stopped. |
| 29 } | 31 } |
| 30 | 32 |
| 31 void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream, | 33 void OmxVideoDecoder::Initialize(DemuxerStream* demuxer_stream, |
| 32 FilterCallback* callback) { | 34 FilterCallback* callback) { |
| 33 if (MessageLoop::current() != message_loop()) { | 35 if (MessageLoop::current() != message_loop_) { |
| 34 message_loop()->PostTask( | 36 message_loop_->PostTask( |
| 35 FROM_HERE, | 37 FROM_HERE, |
| 36 NewRunnableMethod(this, | 38 NewRunnableMethod(this, |
| 37 &OmxVideoDecoder::Initialize, | 39 &OmxVideoDecoder::Initialize, |
| 38 make_scoped_refptr(demuxer_stream), | 40 make_scoped_refptr(demuxer_stream), |
| 39 callback)); | 41 callback)); |
| 40 return; | 42 return; |
| 41 } | 43 } |
| 42 | 44 |
| 43 DCHECK_EQ(message_loop(), MessageLoop::current()); | 45 DCHECK_EQ(message_loop_, MessageLoop::current()); |
| 44 DCHECK(!demuxer_stream_); | 46 DCHECK(!demuxer_stream_); |
| 45 DCHECK(!initialize_callback_.get()); | 47 DCHECK(!initialize_callback_.get()); |
| 46 | 48 |
| 47 initialize_callback_.reset(callback); | 49 initialize_callback_.reset(callback); |
| 48 demuxer_stream_ = demuxer_stream; | 50 demuxer_stream_ = demuxer_stream; |
| 49 | 51 |
| 50 // We require bit stream converter for openmax hardware decoder. | 52 // We require bit stream converter for openmax hardware decoder. |
| 51 demuxer_stream->EnableBitstreamConverter(); | 53 demuxer_stream->EnableBitstreamConverter(); |
| 52 | 54 |
| 53 // Get the AVStream by querying for the provider interface. | 55 // Get the AVStream by querying for the provider interface. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 81 case CODEC_ID_MPEG2VIDEO: | 83 case CODEC_ID_MPEG2VIDEO: |
| 82 config.codec = kCodecMPEG2; break; | 84 config.codec = kCodecMPEG2; break; |
| 83 case CODEC_ID_MPEG4: | 85 case CODEC_ID_MPEG4: |
| 84 config.codec = kCodecMPEG4; break; | 86 config.codec = kCodecMPEG4; break; |
| 85 default: | 87 default: |
| 86 NOTREACHED(); | 88 NOTREACHED(); |
| 87 } | 89 } |
| 88 config.opaque_context = NULL; | 90 config.opaque_context = NULL; |
| 89 config.width = width_; | 91 config.width = width_; |
| 90 config.height = height_; | 92 config.height = height_; |
| 91 decode_engine_->Initialize(message_loop(), this, NULL, config); | 93 decode_engine_->Initialize(message_loop_, this, NULL, config); |
| 92 } | 94 } |
| 93 | 95 |
| 94 void OmxVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { | 96 void OmxVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { |
| 95 DCHECK_EQ(MessageLoop::current(), message_loop()); | 97 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 96 DCHECK(initialize_callback_.get()); | 98 DCHECK(initialize_callback_.get()); |
| 97 | 99 |
| 98 info_ = info; // Save a copy. | 100 info_ = info; // Save a copy. |
| 99 AutoCallbackRunner done_runner(initialize_callback_.release()); | 101 AutoCallbackRunner done_runner(initialize_callback_.release()); |
| 100 | 102 |
| 101 if (info.success) { | 103 if (info.success) { |
| 102 media_format_.SetAsString(MediaFormat::kMimeType, | 104 media_format_.SetAsString(MediaFormat::kMimeType, |
| 103 mime_type::kUncompressedVideo); | 105 mime_type::kUncompressedVideo); |
| 104 media_format_.SetAsInteger(MediaFormat::kWidth, width_); | 106 media_format_.SetAsInteger(MediaFormat::kWidth, width_); |
| 105 media_format_.SetAsInteger(MediaFormat::kHeight, height_); | 107 media_format_.SetAsInteger(MediaFormat::kHeight, height_); |
| 106 media_format_.SetAsInteger( | 108 media_format_.SetAsInteger( |
| 107 MediaFormat::kSurfaceType, | 109 MediaFormat::kSurfaceType, |
| 108 static_cast<int>(info.stream_info.surface_type)); | 110 static_cast<int>(info.stream_info.surface_type)); |
| 109 media_format_.SetAsInteger( | 111 media_format_.SetAsInteger( |
| 110 MediaFormat::kSurfaceFormat, | 112 MediaFormat::kSurfaceFormat, |
| 111 static_cast<int>(info.stream_info.surface_format)); | 113 static_cast<int>(info.stream_info.surface_format)); |
| 112 } else { | 114 } else { |
| 113 host()->SetError(PIPELINE_ERROR_DECODE); | 115 host()->SetError(PIPELINE_ERROR_DECODE); |
| 114 } | 116 } |
| 115 } | 117 } |
| 116 | 118 |
| 117 void OmxVideoDecoder::Stop(FilterCallback* callback) { | 119 void OmxVideoDecoder::Stop(FilterCallback* callback) { |
| 118 if (MessageLoop::current() != message_loop()) { | 120 if (MessageLoop::current() != message_loop_) { |
| 119 message_loop()->PostTask(FROM_HERE, | 121 message_loop_->PostTask(FROM_HERE, |
| 120 NewRunnableMethod(this, | 122 NewRunnableMethod(this, |
| 121 &OmxVideoDecoder::Stop, | 123 &OmxVideoDecoder::Stop, |
| 122 callback)); | 124 callback)); |
| 123 return; | 125 return; |
| 124 } | 126 } |
| 125 | 127 |
| 126 DCHECK_EQ(MessageLoop::current(), message_loop()); | 128 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 127 DCHECK(!uninitialize_callback_.get()); | 129 DCHECK(!uninitialize_callback_.get()); |
| 128 | 130 |
| 129 uninitialize_callback_.reset(callback); | 131 uninitialize_callback_.reset(callback); |
| 130 decode_engine_->Uninitialize(); | 132 decode_engine_->Uninitialize(); |
| 131 } | 133 } |
| 132 | 134 |
| 133 void OmxVideoDecoder::OnUninitializeComplete() { | 135 void OmxVideoDecoder::OnUninitializeComplete() { |
| 134 DCHECK_EQ(MessageLoop::current(), message_loop()); | 136 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 135 DCHECK(uninitialize_callback_.get()); | 137 DCHECK(uninitialize_callback_.get()); |
| 136 | 138 |
| 137 AutoCallbackRunner done_runner(uninitialize_callback_.release()); | 139 AutoCallbackRunner done_runner(uninitialize_callback_.release()); |
| 138 | 140 |
| 139 // TODO(jiesun): Destroy the decoder context. | 141 // TODO(jiesun): Destroy the decoder context. |
| 140 } | 142 } |
| 141 | 143 |
| 142 void OmxVideoDecoder::Flush(FilterCallback* callback) { | 144 void OmxVideoDecoder::Flush(FilterCallback* callback) { |
| 143 if (MessageLoop::current() != message_loop()) { | 145 if (MessageLoop::current() != message_loop_) { |
| 144 message_loop()->PostTask(FROM_HERE, | 146 message_loop_->PostTask(FROM_HERE, |
| 145 NewRunnableMethod(this, | 147 NewRunnableMethod(this, |
| 146 &OmxVideoDecoder::Flush, | 148 &OmxVideoDecoder::Flush, |
| 147 callback)); | 149 callback)); |
| 148 return; | 150 return; |
| 149 } | 151 } |
| 150 | 152 |
| 151 DCHECK_EQ(MessageLoop::current(), message_loop()); | 153 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 152 DCHECK(!flush_callback_.get()); | 154 DCHECK(!flush_callback_.get()); |
| 153 | 155 |
| 154 flush_callback_.reset(callback); | 156 flush_callback_.reset(callback); |
| 155 | 157 |
| 156 decode_engine_->Flush(); | 158 decode_engine_->Flush(); |
| 157 } | 159 } |
| 158 | 160 |
| 159 | 161 |
| 160 void OmxVideoDecoder::OnFlushComplete() { | 162 void OmxVideoDecoder::OnFlushComplete() { |
| 161 DCHECK(flush_callback_.get()); | 163 DCHECK(flush_callback_.get()); |
| 162 | 164 |
| 163 AutoCallbackRunner done_runner(flush_callback_.release()); | 165 AutoCallbackRunner done_runner(flush_callback_.release()); |
| 164 } | 166 } |
| 165 | 167 |
| 166 void OmxVideoDecoder::Seek(base::TimeDelta time, | 168 void OmxVideoDecoder::Seek(base::TimeDelta time, |
| 167 FilterCallback* callback) { | 169 FilterCallback* callback) { |
| 168 if (MessageLoop::current() != message_loop()) { | 170 if (MessageLoop::current() != message_loop_) { |
| 169 message_loop()->PostTask(FROM_HERE, | 171 message_loop_->PostTask(FROM_HERE, |
| 170 NewRunnableMethod(this, | 172 NewRunnableMethod(this, |
| 171 &OmxVideoDecoder::Seek, | 173 &OmxVideoDecoder::Seek, |
| 172 time, | 174 time, |
| 173 callback)); | 175 callback)); |
| 174 return; | 176 return; |
| 175 } | 177 } |
| 176 | 178 |
| 177 DCHECK_EQ(MessageLoop::current(), message_loop()); | 179 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 178 DCHECK(!seek_callback_.get()); | 180 DCHECK(!seek_callback_.get()); |
| 179 | 181 |
| 180 seek_callback_.reset(callback); | 182 seek_callback_.reset(callback); |
| 181 decode_engine_->Seek(); | 183 decode_engine_->Seek(); |
| 182 } | 184 } |
| 183 | 185 |
| 184 void OmxVideoDecoder::OnSeekComplete() { | 186 void OmxVideoDecoder::OnSeekComplete() { |
| 185 DCHECK_EQ(MessageLoop::current(), message_loop()); | 187 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 186 DCHECK(seek_callback_.get()); | 188 DCHECK(seek_callback_.get()); |
| 187 | 189 |
| 188 AutoCallbackRunner done_runner(seek_callback_.release()); | 190 AutoCallbackRunner done_runner(seek_callback_.release()); |
| 189 } | 191 } |
| 190 | 192 |
| 191 void OmxVideoDecoder::OnError() { | 193 void OmxVideoDecoder::OnError() { |
| 192 NOTIMPLEMENTED(); | 194 NOTIMPLEMENTED(); |
| 193 } | 195 } |
| 194 void OmxVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { | 196 void OmxVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { |
| 195 NOTIMPLEMENTED(); | 197 NOTIMPLEMENTED(); |
| 196 } | 198 } |
| 197 | 199 |
| 198 void OmxVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) { | 200 void OmxVideoDecoder::ProduceVideoSample(scoped_refptr<Buffer> buffer) { |
| 199 DCHECK_EQ(message_loop(), MessageLoop::current()); | 201 DCHECK_EQ(message_loop_, MessageLoop::current()); |
| 200 | 202 |
| 201 // Issue more demux. | 203 // Issue more demux. |
| 202 demuxer_stream_->Read(NewCallback(this, &OmxVideoDecoder::DemuxCompleteTask)); | 204 demuxer_stream_->Read(NewCallback(this, &OmxVideoDecoder::DemuxCompleteTask)); |
| 203 } | 205 } |
| 204 | 206 |
| 205 void OmxVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) { | 207 void OmxVideoDecoder::ConsumeVideoFrame(scoped_refptr<VideoFrame> frame) { |
| 206 DCHECK_EQ(message_loop(), MessageLoop::current()); | 208 DCHECK_EQ(message_loop_, MessageLoop::current()); |
| 207 VideoFrameReady(frame); | 209 VideoFrameReady(frame); |
| 208 } | 210 } |
| 209 | 211 |
| 210 void OmxVideoDecoder::ProduceVideoFrame(scoped_refptr<VideoFrame> frame) { | 212 void OmxVideoDecoder::ProduceVideoFrame(scoped_refptr<VideoFrame> frame) { |
| 211 DCHECK(decode_engine_.get()); | 213 DCHECK(decode_engine_.get()); |
| 212 message_loop()->PostTask( | 214 message_loop_->PostTask( |
| 213 FROM_HERE, | 215 FROM_HERE, |
| 214 NewRunnableMethod(decode_engine_.get(), | 216 NewRunnableMethod(decode_engine_.get(), |
| 215 &VideoDecodeEngine::ProduceVideoFrame, frame)); | 217 &VideoDecodeEngine::ProduceVideoFrame, frame)); |
| 216 } | 218 } |
| 217 | 219 |
| 218 bool OmxVideoDecoder::ProvidesBuffer() { | 220 bool OmxVideoDecoder::ProvidesBuffer() { |
| 219 DCHECK(info_.success); | 221 DCHECK(info_.success); |
| 220 return info_.provides_buffers; | 222 return info_.provides_buffers; |
| 221 } | 223 } |
| 222 | 224 |
| 223 const MediaFormat& OmxVideoDecoder::media_format() { | 225 const MediaFormat& OmxVideoDecoder::media_format() { |
| 224 return media_format_; | 226 return media_format_; |
| 225 } | 227 } |
| 226 | 228 |
| 227 void OmxVideoDecoder::DemuxCompleteTask(Buffer* buffer) { | 229 void OmxVideoDecoder::DemuxCompleteTask(Buffer* buffer) { |
| 228 // We simply delicate the buffer to the right message loop. | 230 // We simply delicate the buffer to the right message loop. |
| 229 scoped_refptr<Buffer> ref_buffer = buffer; | 231 scoped_refptr<Buffer> ref_buffer = buffer; |
| 230 DCHECK(decode_engine_.get()); | 232 DCHECK(decode_engine_.get()); |
| 231 message_loop()->PostTask( | 233 message_loop_->PostTask( |
| 232 FROM_HERE, | 234 FROM_HERE, |
| 233 NewRunnableMethod(decode_engine_.get(), | 235 NewRunnableMethod(decode_engine_.get(), |
| 234 &VideoDecodeEngine::ConsumeVideoSample, ref_buffer)); | 236 &VideoDecodeEngine::ConsumeVideoSample, ref_buffer)); |
| 235 } | 237 } |
| 236 | 238 |
| 237 } // namespace media | 239 } // namespace media |
| 238 | 240 |
| 239 // Disable refcounting for the decode engine because it only lives on the | 241 // Disable refcounting for the decode engine because it only lives on the |
| 240 // video decoder thread. | 242 // video decoder thread. |
| 241 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::VideoDecodeEngine); | 243 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::VideoDecodeEngine); |
| OLD | NEW |