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