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 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 // are discarded. | 281 // are discarded. |
282 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 | 282 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 |
283 // until no more data is returned to flush out remaining | 283 // until no more data is returned to flush out remaining |
284 // frames. The input buffer is ignored at this point. | 284 // frames. The input buffer is ignored at this point. |
285 // kDecodeFinished: All calls return empty frames. | 285 // kDecodeFinished: All calls return empty frames. |
286 // kError: Unexpected error happened. | 286 // kError: Unexpected error happened. |
287 // | 287 // |
288 // These are the possible state transitions. | 288 // These are the possible state transitions. |
289 // | 289 // |
290 // kNormal -> kFlushCodec: | 290 // kNormal -> kFlushCodec: |
291 // When buffer->IsEndOfStream() is first true. | 291 // When buffer->end_of_stream() is first true. |
292 // kNormal -> kError: | 292 // kNormal -> kError: |
293 // A decoding error occurs and decoding needs to stop. | 293 // A decoding error occurs and decoding needs to stop. |
294 // kFlushCodec -> kDecodeFinished: | 294 // kFlushCodec -> kDecodeFinished: |
295 // When avcodec_decode_video2() returns 0 data. | 295 // When avcodec_decode_video2() returns 0 data. |
296 // kFlushCodec -> kError: | 296 // kFlushCodec -> kError: |
297 // When avcodec_decode_video2() errors out. | 297 // When avcodec_decode_video2() errors out. |
298 // (any state) -> kNormal: | 298 // (any state) -> kNormal: |
299 // Any time Reset() is called. | 299 // Any time Reset() is called. |
300 | 300 |
301 // Transition to kFlushCodec on the first end of stream buffer. | 301 // Transition to kFlushCodec on the first end of stream buffer. |
302 if (state_ == kNormal && buffer->IsEndOfStream()) { | 302 if (state_ == kNormal && buffer->end_of_stream()) { |
303 state_ = kFlushCodec; | 303 state_ = kFlushCodec; |
304 } | 304 } |
305 | 305 |
306 scoped_refptr<VideoFrame> video_frame; | 306 scoped_refptr<VideoFrame> video_frame; |
307 if (!Decode(buffer, &video_frame)) { | 307 if (!Decode(buffer, &video_frame)) { |
308 state_ = kError; | 308 state_ = kError; |
309 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 309 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
310 return; | 310 return; |
311 } | 311 } |
312 | 312 |
313 // Any successful decode counts! | 313 // Any successful decode counts! |
314 if (!buffer->IsEndOfStream() && buffer->GetDataSize() > 0) { | 314 if (!buffer->end_of_stream() && buffer->data_size() > 0) { |
315 PipelineStatistics statistics; | 315 PipelineStatistics statistics; |
316 statistics.video_bytes_decoded = buffer->GetDataSize(); | 316 statistics.video_bytes_decoded = buffer->data_size(); |
317 statistics_cb_.Run(statistics); | 317 statistics_cb_.Run(statistics); |
318 } | 318 } |
319 | 319 |
320 if (!video_frame.get()) { | 320 if (!video_frame.get()) { |
321 if (state_ == kFlushCodec) { | 321 if (state_ == kFlushCodec) { |
322 DCHECK(buffer->IsEndOfStream()); | 322 DCHECK(buffer->end_of_stream()); |
323 state_ = kDecodeFinished; | 323 state_ = kDecodeFinished; |
324 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); | 324 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); |
325 return; | 325 return; |
326 } | 326 } |
327 | 327 |
328 ReadFromDemuxerStream(); | 328 ReadFromDemuxerStream(); |
329 return; | 329 return; |
330 } | 330 } |
331 | 331 |
332 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); | 332 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); |
333 } | 333 } |
334 | 334 |
335 bool FFmpegVideoDecoder::Decode( | 335 bool FFmpegVideoDecoder::Decode( |
336 const scoped_refptr<DecoderBuffer>& buffer, | 336 const scoped_refptr<DecoderBuffer>& buffer, |
337 scoped_refptr<VideoFrame>* video_frame) { | 337 scoped_refptr<VideoFrame>* video_frame) { |
338 DCHECK(video_frame); | 338 DCHECK(video_frame); |
339 | 339 |
340 // Reset frame to default values. | 340 // Reset frame to default values. |
341 avcodec_get_frame_defaults(av_frame_); | 341 avcodec_get_frame_defaults(av_frame_); |
342 | 342 |
343 // Create a packet for input data. | 343 // Create a packet for input data. |
344 // Due to FFmpeg API changes we no longer have const read-only pointers. | 344 // Due to FFmpeg API changes we no longer have const read-only pointers. |
345 AVPacket packet; | 345 AVPacket packet; |
346 av_init_packet(&packet); | 346 av_init_packet(&packet); |
347 if (buffer->IsEndOfStream()) { | 347 if (buffer->end_of_stream()) { |
348 packet.data = NULL; | 348 packet.data = NULL; |
349 packet.size = 0; | 349 packet.size = 0; |
350 } else { | 350 } else { |
351 packet.data = const_cast<uint8*>(buffer->GetData()); | 351 packet.data = const_cast<uint8*>(buffer->data()); |
352 packet.size = buffer->GetDataSize(); | 352 packet.size = buffer->data_size(); |
353 | 353 |
354 // Let FFmpeg handle presentation timestamp reordering. | 354 // Let FFmpeg handle presentation timestamp reordering. |
355 codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds(); | 355 codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds(); |
356 | 356 |
357 // This is for codecs not using get_buffer to initialize | 357 // This is for codecs not using get_buffer to initialize |
358 // |av_frame_->reordered_opaque| | 358 // |av_frame_->reordered_opaque| |
359 av_frame_->reordered_opaque = codec_context_->reordered_opaque; | 359 av_frame_->reordered_opaque = codec_context_->reordered_opaque; |
360 } | 360 } |
361 | 361 |
362 int frame_decoded = 0; | 362 int frame_decoded = 0; |
363 int result = avcodec_decode_video2(codec_context_, | 363 int result = avcodec_decode_video2(codec_context_, |
364 av_frame_, | 364 av_frame_, |
365 &frame_decoded, | 365 &frame_decoded, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { | 449 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { |
450 ReleaseFFmpegResources(); | 450 ReleaseFFmpegResources(); |
451 return false; | 451 return false; |
452 } | 452 } |
453 | 453 |
454 av_frame_ = avcodec_alloc_frame(); | 454 av_frame_ = avcodec_alloc_frame(); |
455 return true; | 455 return true; |
456 } | 456 } |
457 | 457 |
458 } // namespace media | 458 } // namespace media |
OLD | NEW |