| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this |
| 2 // source code is governed by a BSD-style license that can be found in the | 2 // source code is governed by a BSD-style license that can be found in the |
| 3 // LICENSE file. | 3 // LICENSE file. |
| 4 | 4 |
| 5 #include "media/base/video_frame_impl.h" | 5 #include "media/base/video_frame_impl.h" |
| 6 #include "media/filters/ffmpeg_common.h" | 6 #include "media/filters/ffmpeg_common.h" |
| 7 #include "media/filters/ffmpeg_demuxer.h" | 7 #include "media/filters/ffmpeg_demuxer.h" |
| 8 #include "media/filters/ffmpeg_video_decoder.h" | 8 #include "media/filters/ffmpeg_video_decoder.h" |
| 9 | 9 |
| 10 namespace { | 10 namespace { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 return false; | 88 return false; |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 return true; | 91 return true; |
| 92 } | 92 } |
| 93 | 93 |
| 94 void FFmpegVideoDecoder::OnSeek(base::TimeDelta time) { | 94 void FFmpegVideoDecoder::OnSeek(base::TimeDelta time) { |
| 95 // Everything in the presentation time queue is invalid, clear the queue. | 95 // Everything in the presentation time queue is invalid, clear the queue. |
| 96 while (!pts_queue_.empty()) | 96 while (!pts_queue_.empty()) |
| 97 pts_queue_.pop(); | 97 pts_queue_.pop(); |
| 98 |
| 99 // We're back where we started. It should be completely safe to flush here |
| 100 // since DecoderBase uses |expecting_discontinuous_| to verify that the next |
| 101 // time OnDecode() is called we will have a discontinuous buffer. |
| 102 state_ = kNormal; |
| 103 avcodec_flush_buffers(codec_context_); |
| 98 } | 104 } |
| 99 | 105 |
| 100 void FFmpegVideoDecoder::OnDecode(Buffer* buffer) { | 106 void FFmpegVideoDecoder::OnDecode(Buffer* buffer) { |
| 101 // During decode, because reads are issued asynchronously, it is possible to | 107 // During decode, because reads are issued asynchronously, it is possible to |
| 102 // recieve multiple end of stream buffers since each read is acked. When the | 108 // receive multiple end of stream buffers since each read is acked. When the |
| 103 // first end of stream buffer is read, FFmpeg may still have frames queued | 109 // first end of stream buffer is read, FFmpeg may still have frames queued |
| 104 // up in the decoder so we need to go through the decode loop until it stops | 110 // up in the decoder so we need to go through the decode loop until it stops |
| 105 // giving sensible data. After that, the decoder should output empty | 111 // giving sensible data. After that, the decoder should output empty |
| 106 // frames. There are three states the decoder can be in: | 112 // frames. There are three states the decoder can be in: |
| 107 // | 113 // |
| 108 // kNormal: This is the starting state. Buffers are decoded. Decode errors | 114 // kNormal: This is the starting state. Buffers are decoded. Decode errors |
| 109 // are discarded. | 115 // are discarded. |
| 110 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 | 116 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 |
| 111 // until no more data is returned to flush out remaining | 117 // until no more data is returned to flush out remaining |
| 112 // frames. The input buffer is ignored at this point. | 118 // frames. The input buffer is ignored at this point. |
| 113 // kDecodeFinished: All calls return empty frames. | 119 // kDecodeFinished: All calls return empty frames. |
| 114 // | 120 // |
| 115 // These are the possible state transitions. | 121 // These are the possible state transitions. |
| 116 // | 122 // |
| 117 // kNormal -> kFlushCodec: | 123 // kNormal -> kFlushCodec: |
| 118 // When buffer->IsEndOfStream() is first true. | 124 // When buffer->IsEndOfStream() is first true. |
| 119 // kNormal -> kDecodeFinished: | 125 // kNormal -> kDecodeFinished: |
| 120 // A catastrophic failure occurs, and decoding needs to stop. | 126 // A catastrophic failure occurs, and decoding needs to stop. |
| 121 // kFlushCodec -> kDecodeFinished: | 127 // kFlushCodec -> kDecodeFinished: |
| 122 // When avcodec_decode_video2() returns 0 data or errors out. | 128 // When avcodec_decode_video2() returns 0 data or errors out. |
| 129 // (any state) -> kNormal: |
| 130 // Any time buffer->IsDiscontinuous() is true. |
| 123 // | 131 // |
| 124 // If the decoding is finished, we just always return empty frames. | 132 // If the decoding is finished, we just always return empty frames. |
| 125 if (state_ == kDecodeFinished) { | 133 if (state_ == kDecodeFinished) { |
| 126 EnqueueEmptyFrame(); | 134 EnqueueEmptyFrame(); |
| 127 return; | 135 return; |
| 128 } | 136 } |
| 129 | 137 |
| 130 // Transition to kFlushCodec on the first end of stream buffer. | 138 // Transition to kFlushCodec on the first end of stream buffer. |
| 131 if (state_ == kNormal && buffer->IsEndOfStream()) { | 139 if (state_ == kNormal && buffer->IsEndOfStream()) { |
| 132 state_ = kFlushCodec; | 140 state_ = kFlushCodec; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 | 241 |
| 234 void FFmpegVideoDecoder::EnqueueEmptyFrame() { | 242 void FFmpegVideoDecoder::EnqueueEmptyFrame() { |
| 235 scoped_refptr<VideoFrame> video_frame; | 243 scoped_refptr<VideoFrame> video_frame; |
| 236 VideoFrameImpl::CreateEmptyFrame(&video_frame); | 244 VideoFrameImpl::CreateEmptyFrame(&video_frame); |
| 237 EnqueueResult(video_frame); | 245 EnqueueResult(video_frame); |
| 238 } | 246 } |
| 239 | 247 |
| 240 bool FFmpegVideoDecoder::DecodeFrame(const Buffer& buffer, | 248 bool FFmpegVideoDecoder::DecodeFrame(const Buffer& buffer, |
| 241 AVCodecContext* codec_context, | 249 AVCodecContext* codec_context, |
| 242 AVFrame* yuv_frame) { | 250 AVFrame* yuv_frame) { |
| 243 // Check for discontinuous buffer. If we receive a discontinuous buffer here, | |
| 244 // flush the internal buffer of FFmpeg. | |
| 245 if (buffer.IsDiscontinuous()) { | |
| 246 avcodec_flush_buffers(codec_context); | |
| 247 } | |
| 248 | |
| 249 // Create a packet for input data. | 251 // Create a packet for input data. |
| 250 // Due to FFmpeg API changes we no longer have const read-only pointers. | 252 // Due to FFmpeg API changes we no longer have const read-only pointers. |
| 251 AVPacket packet; | 253 AVPacket packet; |
| 252 av_init_packet(&packet); | 254 av_init_packet(&packet); |
| 253 packet.data = const_cast<uint8*>(buffer.GetData()); | 255 packet.data = const_cast<uint8*>(buffer.GetData()); |
| 254 packet.size = buffer.GetDataSize(); | 256 packet.size = buffer.GetDataSize(); |
| 255 | 257 |
| 256 // We don't allocate AVFrame on the stack since different versions of FFmpeg | 258 // We don't allocate AVFrame on the stack since different versions of FFmpeg |
| 257 // may change the size of AVFrame, causing stack corruption. The solution is | 259 // may change the size of AVFrame, causing stack corruption. The solution is |
| 258 // to let FFmpeg allocate the structure via avcodec_alloc_frame(). | 260 // to let FFmpeg allocate the structure via avcodec_alloc_frame(). |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 // static | 346 // static |
| 345 bool FFmpegVideoDecoder::PtsHeapOrdering::operator()( | 347 bool FFmpegVideoDecoder::PtsHeapOrdering::operator()( |
| 346 const base::TimeDelta& lhs, | 348 const base::TimeDelta& lhs, |
| 347 const base::TimeDelta& rhs) const { | 349 const base::TimeDelta& rhs) const { |
| 348 // std::priority_queue is a max-heap. We want lower timestamps to show up | 350 // std::priority_queue is a max-heap. We want lower timestamps to show up |
| 349 // first so reverse the natural less-than comparison. | 351 // first so reverse the natural less-than comparison. |
| 350 return rhs < lhs; | 352 return rhs < lhs; |
| 351 } | 353 } |
| 352 | 354 |
| 353 } // namespace | 355 } // namespace |
| OLD | NEW |