| 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 // are discarded. | 239 // are discarded. |
| 240 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 | 240 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 |
| 241 // until no more data is returned to flush out remaining | 241 // until no more data is returned to flush out remaining |
| 242 // frames. The input buffer is ignored at this point. | 242 // frames. The input buffer is ignored at this point. |
| 243 // kDecodeFinished: All calls return empty frames. | 243 // kDecodeFinished: All calls return empty frames. |
| 244 // kError: Unexpected error happened. | 244 // kError: Unexpected error happened. |
| 245 // | 245 // |
| 246 // These are the possible state transitions. | 246 // These are the possible state transitions. |
| 247 // | 247 // |
| 248 // kNormal -> kFlushCodec: | 248 // kNormal -> kFlushCodec: |
| 249 // When buffer->IsEndOfStream() is first true. | 249 // When buffer->end_of_stream() is first true. |
| 250 // kNormal -> kError: | 250 // kNormal -> kError: |
| 251 // A decoding error occurs and decoding needs to stop. | 251 // A decoding error occurs and decoding needs to stop. |
| 252 // kFlushCodec -> kDecodeFinished: | 252 // kFlushCodec -> kDecodeFinished: |
| 253 // When avcodec_decode_video2() returns 0 data. | 253 // When avcodec_decode_video2() returns 0 data. |
| 254 // kFlushCodec -> kError: | 254 // kFlushCodec -> kError: |
| 255 // When avcodec_decode_video2() errors out. | 255 // When avcodec_decode_video2() errors out. |
| 256 // (any state) -> kNormal: | 256 // (any state) -> kNormal: |
| 257 // Any time Reset() is called. | 257 // Any time Reset() is called. |
| 258 | 258 |
| 259 // Transition to kFlushCodec on the first end of stream buffer. | 259 // Transition to kFlushCodec on the first end of stream buffer. |
| 260 if (state_ == kNormal && buffer->IsEndOfStream()) { | 260 if (state_ == kNormal && buffer->end_of_stream()) { |
| 261 state_ = kFlushCodec; | 261 state_ = kFlushCodec; |
| 262 } | 262 } |
| 263 | 263 |
| 264 scoped_refptr<VideoFrame> video_frame; | 264 scoped_refptr<VideoFrame> video_frame; |
| 265 if (!FFmpegDecode(buffer, &video_frame)) { | 265 if (!FFmpegDecode(buffer, &video_frame)) { |
| 266 state_ = kError; | 266 state_ = kError; |
| 267 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 267 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 268 return; | 268 return; |
| 269 } | 269 } |
| 270 | 270 |
| 271 if (!video_frame.get()) { | 271 if (!video_frame.get()) { |
| 272 if (state_ == kFlushCodec) { | 272 if (state_ == kFlushCodec) { |
| 273 DCHECK(buffer->IsEndOfStream()); | 273 DCHECK(buffer->end_of_stream()); |
| 274 state_ = kDecodeFinished; | 274 state_ = kDecodeFinished; |
| 275 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); | 275 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); |
| 276 return; | 276 return; |
| 277 } | 277 } |
| 278 | 278 |
| 279 base::ResetAndReturn(&read_cb_).Run(kNotEnoughData, NULL); | 279 base::ResetAndReturn(&read_cb_).Run(kNotEnoughData, NULL); |
| 280 return; | 280 return; |
| 281 } | 281 } |
| 282 | 282 |
| 283 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); | 283 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); |
| 284 } | 284 } |
| 285 | 285 |
| 286 bool FFmpegVideoDecoder::FFmpegDecode( | 286 bool FFmpegVideoDecoder::FFmpegDecode( |
| 287 const scoped_refptr<DecoderBuffer>& buffer, | 287 const scoped_refptr<DecoderBuffer>& buffer, |
| 288 scoped_refptr<VideoFrame>* video_frame) { | 288 scoped_refptr<VideoFrame>* video_frame) { |
| 289 DCHECK(video_frame); | 289 DCHECK(video_frame); |
| 290 | 290 |
| 291 // Reset frame to default values. | 291 // Reset frame to default values. |
| 292 avcodec_get_frame_defaults(av_frame_); | 292 avcodec_get_frame_defaults(av_frame_); |
| 293 | 293 |
| 294 // Create a packet for input data. | 294 // Create a packet for input data. |
| 295 // Due to FFmpeg API changes we no longer have const read-only pointers. | 295 // Due to FFmpeg API changes we no longer have const read-only pointers. |
| 296 AVPacket packet; | 296 AVPacket packet; |
| 297 av_init_packet(&packet); | 297 av_init_packet(&packet); |
| 298 if (buffer->IsEndOfStream()) { | 298 if (buffer->end_of_stream()) { |
| 299 packet.data = NULL; | 299 packet.data = NULL; |
| 300 packet.size = 0; | 300 packet.size = 0; |
| 301 } else { | 301 } else { |
| 302 packet.data = const_cast<uint8*>(buffer->GetData()); | 302 packet.data = const_cast<uint8*>(buffer->data()); |
| 303 packet.size = buffer->GetDataSize(); | 303 packet.size = buffer->data_size(); |
| 304 | 304 |
| 305 // Let FFmpeg handle presentation timestamp reordering. | 305 // Let FFmpeg handle presentation timestamp reordering. |
| 306 codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds(); | 306 codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds(); |
| 307 | 307 |
| 308 // This is for codecs not using get_buffer to initialize | 308 // This is for codecs not using get_buffer to initialize |
| 309 // |av_frame_->reordered_opaque| | 309 // |av_frame_->reordered_opaque| |
| 310 av_frame_->reordered_opaque = codec_context_->reordered_opaque; | 310 av_frame_->reordered_opaque = codec_context_->reordered_opaque; |
| 311 } | 311 } |
| 312 | 312 |
| 313 int frame_decoded = 0; | 313 int frame_decoded = 0; |
| 314 int result = avcodec_decode_video2(codec_context_, | 314 int result = avcodec_decode_video2(codec_context_, |
| 315 av_frame_, | 315 av_frame_, |
| 316 &frame_decoded, | 316 &frame_decoded, |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { | 388 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { |
| 389 ReleaseFFmpegResources(); | 389 ReleaseFFmpegResources(); |
| 390 return false; | 390 return false; |
| 391 } | 391 } |
| 392 | 392 |
| 393 av_frame_ = avcodec_alloc_frame(); | 393 av_frame_ = avcodec_alloc_frame(); |
| 394 return true; | 394 return true; |
| 395 } | 395 } |
| 396 | 396 |
| 397 } // namespace media | 397 } // namespace media |
| OLD | NEW |