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 |