OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
226 demuxer_stream_->Read(base::Bind( | 226 demuxer_stream_->Read(base::Bind( |
227 &FFmpegVideoDecoder::BufferReady, weak_this_)); | 227 &FFmpegVideoDecoder::BufferReady, weak_this_)); |
228 } | 228 } |
229 | 229 |
230 void FFmpegVideoDecoder::BufferReady( | 230 void FFmpegVideoDecoder::BufferReady( |
231 DemuxerStream::Status status, | 231 DemuxerStream::Status status, |
232 const scoped_refptr<DecoderBuffer>& buffer) { | 232 const scoped_refptr<DecoderBuffer>& buffer) { |
233 DCHECK(message_loop_->BelongsToCurrentThread()); | 233 DCHECK(message_loop_->BelongsToCurrentThread()); |
234 DCHECK_NE(state_, kDecodeFinished); | 234 DCHECK_NE(state_, kDecodeFinished); |
235 DCHECK_NE(state_, kError); | 235 DCHECK_NE(state_, kError); |
236 DCHECK_EQ(status != DemuxerStream::kOk, !buffer) << status; | 236 DCHECK_EQ(status != DemuxerStream::kOk, !buffer.get()) << status; |
237 | 237 |
238 if (state_ == kUninitialized) | 238 if (state_ == kUninitialized) |
239 return; | 239 return; |
240 | 240 |
241 DCHECK(!read_cb_.is_null()); | 241 DCHECK(!read_cb_.is_null()); |
242 | 242 |
243 if (!reset_cb_.is_null()) { | 243 if (!reset_cb_.is_null()) { |
244 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); | 244 base::ResetAndReturn(&read_cb_).Run(kOk, NULL); |
245 DoReset(); | 245 DoReset(); |
246 return; | 246 return; |
(...skipping 10 matching lines...) Expand all Loading... |
257 } | 257 } |
258 | 258 |
259 void FFmpegVideoDecoder::DecodeBuffer( | 259 void FFmpegVideoDecoder::DecodeBuffer( |
260 const scoped_refptr<DecoderBuffer>& buffer) { | 260 const scoped_refptr<DecoderBuffer>& buffer) { |
261 DCHECK(message_loop_->BelongsToCurrentThread()); | 261 DCHECK(message_loop_->BelongsToCurrentThread()); |
262 DCHECK_NE(state_, kUninitialized); | 262 DCHECK_NE(state_, kUninitialized); |
263 DCHECK_NE(state_, kDecodeFinished); | 263 DCHECK_NE(state_, kDecodeFinished); |
264 DCHECK_NE(state_, kError); | 264 DCHECK_NE(state_, kError); |
265 DCHECK(reset_cb_.is_null()); | 265 DCHECK(reset_cb_.is_null()); |
266 DCHECK(!read_cb_.is_null()); | 266 DCHECK(!read_cb_.is_null()); |
267 DCHECK(buffer); | 267 DCHECK(buffer.get()); |
268 | 268 |
269 // During decode, because reads are issued asynchronously, it is possible to | 269 // During decode, because reads are issued asynchronously, it is possible to |
270 // receive multiple end of stream buffers since each read is acked. When the | 270 // receive multiple end of stream buffers since each read is acked. When the |
271 // first end of stream buffer is read, FFmpeg may still have frames queued | 271 // first end of stream buffer is read, FFmpeg may still have frames queued |
272 // up in the decoder so we need to go through the decode loop until it stops | 272 // up in the decoder so we need to go through the decode loop until it stops |
273 // giving sensible data. After that, the decoder should output empty | 273 // giving sensible data. After that, the decoder should output empty |
274 // frames. There are three states the decoder can be in: | 274 // frames. There are three states the decoder can be in: |
275 // | 275 // |
276 // kNormal: This is the starting state. Buffers are decoded. Decode errors | 276 // kNormal: This is the starting state. Buffers are decoded. Decode errors |
277 // are discarded. | 277 // are discarded. |
(...skipping 28 matching lines...) Expand all Loading... |
306 return; | 306 return; |
307 } | 307 } |
308 | 308 |
309 // Any successful decode counts! | 309 // Any successful decode counts! |
310 if (!buffer->IsEndOfStream() && buffer->GetDataSize() > 0) { | 310 if (!buffer->IsEndOfStream() && buffer->GetDataSize() > 0) { |
311 PipelineStatistics statistics; | 311 PipelineStatistics statistics; |
312 statistics.video_bytes_decoded = buffer->GetDataSize(); | 312 statistics.video_bytes_decoded = buffer->GetDataSize(); |
313 statistics_cb_.Run(statistics); | 313 statistics_cb_.Run(statistics); |
314 } | 314 } |
315 | 315 |
316 if (!video_frame) { | 316 if (!video_frame.get()) { |
317 if (state_ == kFlushCodec) { | 317 if (state_ == kFlushCodec) { |
318 DCHECK(buffer->IsEndOfStream()); | 318 DCHECK(buffer->IsEndOfStream()); |
319 state_ = kDecodeFinished; | 319 state_ = kDecodeFinished; |
320 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); | 320 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); |
321 return; | 321 return; |
322 } | 322 } |
323 | 323 |
324 ReadFromDemuxerStream(); | 324 ReadFromDemuxerStream(); |
325 return; | 325 return; |
326 } | 326 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { | 445 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { |
446 ReleaseFFmpegResources(); | 446 ReleaseFFmpegResources(); |
447 return false; | 447 return false; |
448 } | 448 } |
449 | 449 |
450 av_frame_ = avcodec_alloc_frame(); | 450 av_frame_ = avcodec_alloc_frame(); |
451 return true; | 451 return true; |
452 } | 452 } |
453 | 453 |
454 } // namespace media | 454 } // namespace media |
OLD | NEW |