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/ffmpeg_video_decoder.h" | 5 #include "media/filters/ffmpeg_video_decoder.h" |
6 | 6 |
7 #include <deque> | 7 #include <deque> |
8 | 8 |
9 #include "base/task.h" | 9 #include "base/task.h" |
10 #include "media/base/callback.h" | 10 #include "media/base/callback.h" |
11 #include "media/base/filters.h" | 11 #include "media/base/filters.h" |
12 #include "media/base/filter_host.h" | 12 #include "media/base/filter_host.h" |
13 #include "media/base/limits.h" | 13 #include "media/base/limits.h" |
14 #include "media/base/media_format.h" | 14 #include "media/base/media_format.h" |
15 #include "media/base/video_frame.h" | 15 #include "media/base/video_frame.h" |
16 #include "media/ffmpeg/ffmpeg_common.h" | 16 #include "media/ffmpeg/ffmpeg_common.h" |
17 #include "media/ffmpeg/ffmpeg_util.h" | 17 #include "media/ffmpeg/ffmpeg_util.h" |
18 #include "media/filters/ffmpeg_interfaces.h" | 18 #include "media/filters/ffmpeg_interfaces.h" |
19 #include "media/filters/ffmpeg_video_decode_engine.h" | 19 #include "media/filters/ffmpeg_video_decode_engine.h" |
20 #include "media/filters/video_decode_engine.h" | 20 #include "media/filters/video_decode_engine.h" |
21 | 21 |
22 namespace media { | 22 namespace media { |
23 | 23 |
24 FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeEngine* engine) | 24 FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeEngine* engine) |
25 : width_(0), | 25 : width_(0), |
26 height_(0), | 26 height_(0), |
27 time_base_(new AVRational()), | 27 time_base_(new AVRational()), |
28 state_(kUnInitialized), | 28 state_(kUnInitialized), |
29 decode_engine_(engine), | 29 decode_engine_(engine) { |
30 pending_reads_(0), | |
31 pending_requests_(0) { | |
32 memset(&info_, 0, sizeof(info_)); | 30 memset(&info_, 0, sizeof(info_)); |
33 } | 31 } |
34 | 32 |
35 FFmpegVideoDecoder::~FFmpegVideoDecoder() { | 33 FFmpegVideoDecoder::~FFmpegVideoDecoder() { |
36 } | 34 } |
37 | 35 |
38 void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, | 36 void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, |
39 FilterCallback* callback) { | 37 FilterCallback* callback) { |
40 if (MessageLoop::current() != message_loop()) { | 38 if (MessageLoop::current() != message_loop()) { |
41 message_loop()->PostTask(FROM_HERE, | 39 message_loop()->PostTask(FROM_HERE, |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 } | 141 } |
144 | 142 |
145 void FFmpegVideoDecoder::OnUninitializeComplete() { | 143 void FFmpegVideoDecoder::OnUninitializeComplete() { |
146 DCHECK_EQ(MessageLoop::current(), message_loop()); | 144 DCHECK_EQ(MessageLoop::current(), message_loop()); |
147 DCHECK(uninitialize_callback_.get()); | 145 DCHECK(uninitialize_callback_.get()); |
148 | 146 |
149 AutoCallbackRunner done_runner(uninitialize_callback_.release()); | 147 AutoCallbackRunner done_runner(uninitialize_callback_.release()); |
150 state_ = kStopped; | 148 state_ = kStopped; |
151 } | 149 } |
152 | 150 |
| 151 void FFmpegVideoDecoder::Pause(FilterCallback* callback) { |
| 152 if (MessageLoop::current() != message_loop()) { |
| 153 message_loop()->PostTask(FROM_HERE, |
| 154 NewRunnableMethod(this, |
| 155 &FFmpegVideoDecoder::Pause, |
| 156 callback)); |
| 157 return; |
| 158 } |
| 159 |
| 160 AutoCallbackRunner done_runner(callback); |
| 161 state_ = kPausing; |
| 162 } |
| 163 |
153 void FFmpegVideoDecoder::Flush(FilterCallback* callback) { | 164 void FFmpegVideoDecoder::Flush(FilterCallback* callback) { |
154 if (MessageLoop::current() != message_loop()) { | 165 if (MessageLoop::current() != message_loop()) { |
155 message_loop()->PostTask(FROM_HERE, | 166 message_loop()->PostTask(FROM_HERE, |
156 NewRunnableMethod(this, | 167 NewRunnableMethod(this, |
157 &FFmpegVideoDecoder::Flush, | 168 &FFmpegVideoDecoder::Flush, |
158 callback)); | 169 callback)); |
159 return; | 170 return; |
160 } | 171 } |
161 | 172 |
162 DCHECK_EQ(MessageLoop::current(), message_loop()); | 173 DCHECK_EQ(MessageLoop::current(), message_loop()); |
163 DCHECK(!flush_callback_.get()); | 174 DCHECK(!flush_callback_.get()); |
164 | 175 |
| 176 state_ = kFlushing; |
| 177 |
| 178 FlushBuffers(); |
| 179 |
165 flush_callback_.reset(callback); | 180 flush_callback_.reset(callback); |
166 | 181 |
167 // Everything in the presentation time queue is invalid, clear the queue. | |
168 while (!pts_heap_.IsEmpty()) | |
169 pts_heap_.Pop(); | |
170 | |
171 decode_engine_->Flush(); | 182 decode_engine_->Flush(); |
172 } | 183 } |
173 | 184 |
174 void FFmpegVideoDecoder::OnFlushComplete() { | 185 void FFmpegVideoDecoder::OnFlushComplete() { |
175 DCHECK_EQ(MessageLoop::current(), message_loop()); | 186 DCHECK_EQ(MessageLoop::current(), message_loop()); |
176 DCHECK(flush_callback_.get()); | 187 DCHECK(flush_callback_.get()); |
177 | 188 |
178 AutoCallbackRunner done_runner(flush_callback_.release()); | 189 AutoCallbackRunner done_runner(flush_callback_.release()); |
| 190 |
| 191 // Everything in the presentation time queue is invalid, clear the queue. |
| 192 while (!pts_heap_.IsEmpty()) |
| 193 pts_heap_.Pop(); |
| 194 |
| 195 // Mark flush operation had been done. |
| 196 state_ = kNormal; |
179 } | 197 } |
180 | 198 |
181 void FFmpegVideoDecoder::Seek(base::TimeDelta time, | 199 void FFmpegVideoDecoder::Seek(base::TimeDelta time, |
182 FilterCallback* callback) { | 200 FilterCallback* callback) { |
183 if (MessageLoop::current() != message_loop()) { | 201 if (MessageLoop::current() != message_loop()) { |
184 message_loop()->PostTask(FROM_HERE, | 202 message_loop()->PostTask(FROM_HERE, |
185 NewRunnableMethod(this, | 203 NewRunnableMethod(this, |
186 &FFmpegVideoDecoder::Seek, | 204 &FFmpegVideoDecoder::Seek, |
187 time, | 205 time, |
188 callback)); | 206 callback)); |
189 return; | 207 return; |
190 } | 208 } |
191 | 209 |
192 DCHECK_EQ(MessageLoop::current(), message_loop()); | 210 DCHECK_EQ(MessageLoop::current(), message_loop()); |
193 DCHECK(!seek_callback_.get()); | 211 DCHECK(!seek_callback_.get()); |
194 | 212 |
195 // TODO(jiesun): when we move to parallel Flush, we should remove this. | |
196 DCHECK_EQ(0u, pending_reads_) << "Pending reads should have completed"; | |
197 DCHECK_EQ(0u, pending_requests_) << "Pending requests should be empty"; | |
198 | |
199 seek_callback_.reset(callback); | 213 seek_callback_.reset(callback); |
200 decode_engine_->Seek(); | 214 decode_engine_->Seek(); |
201 } | 215 } |
202 | 216 |
203 void FFmpegVideoDecoder::OnSeekComplete() { | 217 void FFmpegVideoDecoder::OnSeekComplete() { |
204 DCHECK_EQ(MessageLoop::current(), message_loop()); | 218 DCHECK_EQ(MessageLoop::current(), message_loop()); |
205 DCHECK(seek_callback_.get()); | 219 DCHECK(seek_callback_.get()); |
206 | 220 |
207 AutoCallbackRunner done_runner(seek_callback_.release()); | 221 AutoCallbackRunner done_runner(seek_callback_.release()); |
208 state_ = kNormal; | |
209 } | 222 } |
210 | 223 |
211 void FFmpegVideoDecoder::OnError() { | 224 void FFmpegVideoDecoder::OnError() { |
212 NOTIMPLEMENTED(); | 225 NOTIMPLEMENTED(); |
213 } | 226 } |
214 | 227 |
215 void FFmpegVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { | 228 void FFmpegVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { |
216 NOTIMPLEMENTED(); | 229 NOTIMPLEMENTED(); |
217 } | 230 } |
218 | 231 |
219 void FFmpegVideoDecoder::OnReadComplete(Buffer* buffer_in) { | 232 void FFmpegVideoDecoder::OnReadComplete(Buffer* buffer_in) { |
220 scoped_refptr<Buffer> buffer = buffer_in; | 233 scoped_refptr<Buffer> buffer = buffer_in; |
221 message_loop()->PostTask( | 234 message_loop()->PostTask( |
222 FROM_HERE, | 235 FROM_HERE, |
223 NewRunnableMethod(this, | 236 NewRunnableMethod(this, |
224 &FFmpegVideoDecoder::OnReadCompleteTask, | 237 &FFmpegVideoDecoder::OnReadCompleteTask, |
225 buffer)); | 238 buffer)); |
226 } | 239 } |
227 | 240 |
228 void FFmpegVideoDecoder::OnReadCompleteTask(scoped_refptr<Buffer> buffer) { | 241 void FFmpegVideoDecoder::OnReadCompleteTask(scoped_refptr<Buffer> buffer) { |
229 DCHECK_EQ(MessageLoop::current(), message_loop()); | 242 DCHECK_EQ(MessageLoop::current(), message_loop()); |
230 DCHECK_GT(pending_reads_, 0u); | 243 DCHECK_NE(state_, kStopped); // because of Flush() before Stop(). |
231 | |
232 --pending_reads_; | |
233 | 244 |
234 // During decode, because reads are issued asynchronously, it is possible to | 245 // During decode, because reads are issued asynchronously, it is possible to |
235 // receive multiple end of stream buffers since each read is acked. When the | 246 // receive multiple end of stream buffers since each read is acked. When the |
236 // first end of stream buffer is read, FFmpeg may still have frames queued | 247 // first end of stream buffer is read, FFmpeg may still have frames queued |
237 // up in the decoder so we need to go through the decode loop until it stops | 248 // up in the decoder so we need to go through the decode loop until it stops |
238 // giving sensible data. After that, the decoder should output empty | 249 // giving sensible data. After that, the decoder should output empty |
239 // frames. There are three states the decoder can be in: | 250 // frames. There are three states the decoder can be in: |
240 // | 251 // |
241 // kNormal: This is the starting state. Buffers are decoded. Decode errors | 252 // kNormal: This is the starting state. Buffers are decoded. Decode errors |
242 // are discarded. | 253 // are discarded. |
243 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 | 254 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 |
244 // until no more data is returned to flush out remaining | 255 // until no more data is returned to flush out remaining |
245 // frames. The input buffer is ignored at this point. | 256 // frames. The input buffer is ignored at this point. |
246 // kDecodeFinished: All calls return empty frames. | 257 // kDecodeFinished: All calls return empty frames. |
247 // | 258 // |
248 // These are the possible state transitions. | 259 // These are the possible state transitions. |
249 // | 260 // |
250 // kNormal -> kFlushCodec: | 261 // kNormal -> kFlushCodec: |
251 // When buffer->IsEndOfStream() is first true. | 262 // When buffer->IsEndOfStream() is first true. |
252 // kNormal -> kDecodeFinished: | 263 // kNormal -> kDecodeFinished: |
253 // A catastrophic failure occurs, and decoding needs to stop. | 264 // A catastrophic failure occurs, and decoding needs to stop. |
254 // kFlushCodec -> kDecodeFinished: | 265 // kFlushCodec -> kDecodeFinished: |
255 // When avcodec_decode_video2() returns 0 data or errors out. | 266 // When avcodec_decode_video2() returns 0 data or errors out. |
256 // (any state) -> kNormal: | 267 // (any state) -> kNormal: |
257 // Any time buffer->IsDiscontinuous() is true. | 268 // Any time buffer->IsDiscontinuous() is true. |
258 // | |
259 // If the decoding is finished, we just always return empty frames. | |
260 if (state_ == kDecodeFinished || state_ == kStopped) { | |
261 DCHECK(buffer->IsEndOfStream()); | |
262 | |
263 --pending_requests_; | |
264 // Signal VideoRenderer the end of the stream event. | |
265 scoped_refptr<VideoFrame> video_frame; | |
266 VideoFrame::CreateEmptyFrame(&video_frame); | |
267 fill_buffer_done_callback()->Run(video_frame); | |
268 return; | |
269 } | |
270 | 269 |
271 // Transition to kFlushCodec on the first end of stream buffer. | 270 // Transition to kFlushCodec on the first end of stream buffer. |
272 if (state_ == kNormal && buffer->IsEndOfStream()) { | 271 if (state_ == kNormal && buffer->IsEndOfStream()) { |
273 state_ = kFlushCodec; | 272 state_ = kFlushCodec; |
274 } | 273 } |
275 | 274 |
276 // Push all incoming timestamps into the priority queue as long as we have | 275 // Push all incoming timestamps into the priority queue as long as we have |
277 // not yet received an end of stream buffer. It is important that this line | 276 // not yet received an end of stream buffer. It is important that this line |
278 // stay below the state transition into kFlushCodec done above. | 277 // stay below the state transition into kFlushCodec done above. |
279 // | 278 // |
(...skipping 15 matching lines...) Expand all Loading... |
295 FROM_HERE, | 294 FROM_HERE, |
296 NewRunnableMethod(this, | 295 NewRunnableMethod(this, |
297 &FFmpegVideoDecoder::FillThisBuffer, | 296 &FFmpegVideoDecoder::FillThisBuffer, |
298 video_frame)); | 297 video_frame)); |
299 return; | 298 return; |
300 } | 299 } |
301 | 300 |
302 DCHECK_EQ(MessageLoop::current(), message_loop()); | 301 DCHECK_EQ(MessageLoop::current(), message_loop()); |
303 | 302 |
304 // Synchronized flushing before stop should prevent this. | 303 // Synchronized flushing before stop should prevent this. |
305 if (state_ == kStopped) | 304 DCHECK_NE(state_, kStopped); |
306 return; // Discard the video frame. | 305 |
| 306 // If the decoding is finished, we just always return empty frames. |
| 307 if (state_ == kDecodeFinished) { |
| 308 // Signal VideoRenderer the end of the stream event. |
| 309 scoped_refptr<VideoFrame> empty_frame; |
| 310 VideoFrame::CreateEmptyFrame(&empty_frame); |
| 311 fill_buffer_done_callback()->Run(empty_frame); |
| 312 |
| 313 // Fall through, because we still need to keep record of this frame. |
| 314 } |
307 | 315 |
308 // Notify decode engine the available of new frame. | 316 // Notify decode engine the available of new frame. |
309 ++pending_requests_; | |
310 decode_engine_->FillThisBuffer(video_frame); | 317 decode_engine_->FillThisBuffer(video_frame); |
311 } | 318 } |
312 | 319 |
313 void FFmpegVideoDecoder::OnFillBufferCallback( | 320 void FFmpegVideoDecoder::OnFillBufferCallback( |
314 scoped_refptr<VideoFrame> video_frame) { | 321 scoped_refptr<VideoFrame> video_frame) { |
315 DCHECK_EQ(MessageLoop::current(), message_loop()); | 322 DCHECK_EQ(MessageLoop::current(), message_loop()); |
316 | 323 DCHECK_NE(state_, kStopped); |
317 // TODO(jiesun): Flush before stop will prevent this from happening. | |
318 if (state_ == kStopped) | |
319 return; // Discard the video frame. | |
320 | 324 |
321 if (video_frame.get()) { | 325 if (video_frame.get()) { |
| 326 if (kPausing == state_ || kFlushing == state_) { |
| 327 frame_queue_flushed_.push_back(video_frame); |
| 328 if (kFlushing == state_) |
| 329 FlushBuffers(); |
| 330 return; |
| 331 } |
| 332 |
322 // If we actually got data back, enqueue a frame. | 333 // If we actually got data back, enqueue a frame. |
323 last_pts_ = FindPtsAndDuration(*time_base_, &pts_heap_, last_pts_, | 334 last_pts_ = FindPtsAndDuration(*time_base_, &pts_heap_, last_pts_, |
324 video_frame.get()); | 335 video_frame.get()); |
325 | 336 |
326 video_frame->SetTimestamp(last_pts_.timestamp); | 337 video_frame->SetTimestamp(last_pts_.timestamp); |
327 video_frame->SetDuration(last_pts_.duration); | 338 video_frame->SetDuration(last_pts_.duration); |
328 | 339 |
329 // Deliver this frame to VideoRenderer. | |
330 --pending_requests_; | |
331 fill_buffer_done_callback()->Run(video_frame); | 340 fill_buffer_done_callback()->Run(video_frame); |
332 } else { | 341 } else { |
333 // When in kFlushCodec, any errored decode, or a 0-lengthed frame, | 342 // When in kFlushCodec, any errored decode, or a 0-lengthed frame, |
334 // is taken as a signal to stop decoding. | 343 // is taken as a signal to stop decoding. |
335 if (state_ == kFlushCodec) { | 344 if (state_ == kFlushCodec) { |
336 state_ = kDecodeFinished; | 345 state_ = kDecodeFinished; |
337 | 346 |
338 --pending_requests_; | |
339 // Signal VideoRenderer the end of the stream event. | 347 // Signal VideoRenderer the end of the stream event. |
340 scoped_refptr<VideoFrame> video_frame; | 348 scoped_refptr<VideoFrame> video_frame; |
341 VideoFrame::CreateEmptyFrame(&video_frame); | 349 VideoFrame::CreateEmptyFrame(&video_frame); |
342 fill_buffer_done_callback()->Run(video_frame); | 350 fill_buffer_done_callback()->Run(video_frame); |
343 } | 351 } |
344 } | 352 } |
345 } | 353 } |
346 | 354 |
347 void FFmpegVideoDecoder::OnEmptyBufferCallback( | 355 void FFmpegVideoDecoder::OnEmptyBufferCallback( |
348 scoped_refptr<Buffer> buffer) { | 356 scoped_refptr<Buffer> buffer) { |
349 DCHECK_EQ(MessageLoop::current(), message_loop()); | 357 DCHECK_EQ(MessageLoop::current(), message_loop()); |
350 DCHECK_LE(pending_reads_, pending_requests_); | 358 DCHECK_NE(state_, kStopped); |
351 | 359 |
352 demuxer_stream_->Read( | 360 demuxer_stream_->Read( |
353 NewCallback(this, &FFmpegVideoDecoder::OnReadComplete)); | 361 NewCallback(this, &FFmpegVideoDecoder::OnReadComplete)); |
354 ++pending_reads_; | |
355 } | 362 } |
356 | 363 |
357 FFmpegVideoDecoder::TimeTuple FFmpegVideoDecoder::FindPtsAndDuration( | 364 FFmpegVideoDecoder::TimeTuple FFmpegVideoDecoder::FindPtsAndDuration( |
358 const AVRational& time_base, | 365 const AVRational& time_base, |
359 PtsHeap* pts_heap, | 366 PtsHeap* pts_heap, |
360 const TimeTuple& last_pts, | 367 const TimeTuple& last_pts, |
361 const VideoFrame* frame) { | 368 const VideoFrame* frame) { |
362 TimeTuple pts; | 369 TimeTuple pts; |
363 | 370 |
364 // First search the VideoFrame for the pts. This is the most authoritative. | 371 // First search the VideoFrame for the pts. This is the most authoritative. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 } | 408 } |
402 | 409 |
403 return pts; | 410 return pts; |
404 } | 411 } |
405 | 412 |
406 bool FFmpegVideoDecoder::ProvidesBuffer() { | 413 bool FFmpegVideoDecoder::ProvidesBuffer() { |
407 DCHECK(info_.success_); | 414 DCHECK(info_.success_); |
408 return info_.provides_buffers_; | 415 return info_.provides_buffers_; |
409 } | 416 } |
410 | 417 |
| 418 void FFmpegVideoDecoder::FlushBuffers() { |
| 419 while (!frame_queue_flushed_.empty()) { |
| 420 scoped_refptr<VideoFrame> video_frame; |
| 421 video_frame = frame_queue_flushed_.front(); |
| 422 frame_queue_flushed_.pop_front(); |
| 423 |
| 424 // Depends on who own the buffers, we either return it to the renderer |
| 425 // or return it to the decode engine. |
| 426 if (ProvidesBuffer()) |
| 427 decode_engine_->FillThisBuffer(video_frame); |
| 428 else |
| 429 fill_buffer_done_callback()->Run(video_frame); |
| 430 } |
| 431 } |
| 432 |
411 void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( | 433 void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( |
412 VideoDecodeEngine* engine) { | 434 VideoDecodeEngine* engine) { |
413 decode_engine_ = engine; | 435 decode_engine_ = engine; |
414 } | 436 } |
415 | 437 |
416 // static | 438 // static |
417 FilterFactory* FFmpegVideoDecoder::CreateFactory() { | 439 FilterFactory* FFmpegVideoDecoder::CreateFactory() { |
418 return new FilterFactoryImpl1<FFmpegVideoDecoder, FFmpegVideoDecodeEngine*>( | 440 return new FilterFactoryImpl1<FFmpegVideoDecoder, FFmpegVideoDecodeEngine*>( |
419 new FFmpegVideoDecodeEngine()); | 441 new FFmpegVideoDecodeEngine()); |
420 } | 442 } |
421 | 443 |
422 // static | 444 // static |
423 bool FFmpegVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { | 445 bool FFmpegVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { |
424 std::string mime_type; | 446 std::string mime_type; |
425 return format.GetAsString(MediaFormat::kMimeType, &mime_type) && | 447 return format.GetAsString(MediaFormat::kMimeType, &mime_type) && |
426 mime_type::kFFmpegVideo == mime_type; | 448 mime_type::kFFmpegVideo == mime_type; |
427 } | 449 } |
428 | 450 |
429 } // namespace media | 451 } // namespace media |
OLD | NEW |