Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: media/filters/ffmpeg_video_decoder.cc

Issue 10832087: Remove VideoDecoderConfig.frame_rate_xxx() & VideoFrame:Get/SetDuration() (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address more CR comments. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 return decode_threads; 53 return decode_threads;
54 } 54 }
55 55
56 FFmpegVideoDecoder::FFmpegVideoDecoder( 56 FFmpegVideoDecoder::FFmpegVideoDecoder(
57 const base::Callback<MessageLoop*()>& message_loop_cb) 57 const base::Callback<MessageLoop*()>& message_loop_cb)
58 : message_loop_factory_cb_(message_loop_cb), 58 : message_loop_factory_cb_(message_loop_cb),
59 message_loop_(NULL), 59 message_loop_(NULL),
60 state_(kUninitialized), 60 state_(kUninitialized),
61 codec_context_(NULL), 61 codec_context_(NULL),
62 av_frame_(NULL), 62 av_frame_(NULL),
63 frame_rate_numerator_(0),
64 frame_rate_denominator_(0),
65 decryptor_(NULL) { 63 decryptor_(NULL) {
66 } 64 }
67 65
68 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, 66 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context,
69 AVFrame* frame) { 67 AVFrame* frame) {
70 // Don't use |codec_context_| here! With threaded decoding, 68 // Don't use |codec_context_| here! With threaded decoding,
71 // it will contain unsynchronized width/height/pix_fmt values, 69 // it will contain unsynchronized width/height/pix_fmt values,
72 // whereas |codec_context| contains the current threads's 70 // whereas |codec_context| contains the current threads's
73 // updated width/height/pix_fmt, which can change for adaptive 71 // updated width/height/pix_fmt, which can change for adaptive
74 // content. 72 // content.
75 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt); 73 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
76 if (format == VideoFrame::INVALID) 74 if (format == VideoFrame::INVALID)
77 return AVERROR(EINVAL); 75 return AVERROR(EINVAL);
78 DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16); 76 DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16);
79 77
80 int width = codec_context->width; 78 int width = codec_context->width;
81 int height = codec_context->height; 79 int height = codec_context->height;
82 int ret; 80 int ret;
83 if ((ret = av_image_check_size(width, height, 0, NULL)) < 0) 81 if ((ret = av_image_check_size(width, height, 0, NULL)) < 0)
84 return ret; 82 return ret;
85 83
86 scoped_refptr<VideoFrame> video_frame = 84 scoped_refptr<VideoFrame> video_frame =
87 VideoFrame::CreateFrame(format, width, height, 85 VideoFrame::CreateFrame(format, width, height, kNoTimestamp());
88 kNoTimestamp(), kNoTimestamp());
89 86
90 for (int i = 0; i < 3; i++) { 87 for (int i = 0; i < 3; i++) {
91 frame->base[i] = video_frame->data(i); 88 frame->base[i] = video_frame->data(i);
92 frame->data[i] = video_frame->data(i); 89 frame->data[i] = video_frame->data(i);
93 frame->linesize[i] = video_frame->stride(i); 90 frame->linesize[i] = video_frame->stride(i);
94 } 91 }
95 92
96 frame->opaque = video_frame.release(); 93 frame->opaque = video_frame.release();
97 frame->type = FF_BUFFER_TYPE_USER; 94 frame->type = FF_BUFFER_TYPE_USER;
98 frame->pkt_pts = codec_context->pkt ? codec_context->pkt->pts : 95 frame->pkt_pts = codec_context->pkt ? codec_context->pkt->pts :
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 179
183 if (avcodec_open2(codec_context_, codec, NULL) < 0) { 180 if (avcodec_open2(codec_context_, codec, NULL) < 0) {
184 status_cb.Run(PIPELINE_ERROR_DECODE); 181 status_cb.Run(PIPELINE_ERROR_DECODE);
185 return; 182 return;
186 } 183 }
187 184
188 // Success! 185 // Success!
189 state_ = kNormal; 186 state_ = kNormal;
190 av_frame_ = avcodec_alloc_frame(); 187 av_frame_ = avcodec_alloc_frame();
191 natural_size_ = config.natural_size(); 188 natural_size_ = config.natural_size();
192 frame_rate_numerator_ = config.frame_rate_numerator();
193 frame_rate_denominator_ = config.frame_rate_denominator();
194 status_cb.Run(PIPELINE_OK); 189 status_cb.Run(PIPELINE_OK);
195 } 190 }
196 191
197 void FFmpegVideoDecoder::Read(const ReadCB& read_cb) { 192 void FFmpegVideoDecoder::Read(const ReadCB& read_cb) {
198 // Complete operation asynchronously on different stack of execution as per 193 // Complete operation asynchronously on different stack of execution as per
199 // the API contract of VideoDecoder::Read() 194 // the API contract of VideoDecoder::Read()
200 message_loop_->PostTask(FROM_HERE, base::Bind( 195 message_loop_->PostTask(FROM_HERE, base::Bind(
201 &FFmpegVideoDecoder::DoRead, this, read_cb)); 196 &FFmpegVideoDecoder::DoRead, this, read_cb));
202 } 197 }
203 198
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 *video_frame = NULL; 493 *video_frame = NULL;
499 return false; 494 return false;
500 } 495 }
501 496
502 if (!av_frame_->opaque) { 497 if (!av_frame_->opaque) {
503 LOG(ERROR) << "VideoFrame object associated with frame data not set."; 498 LOG(ERROR) << "VideoFrame object associated with frame data not set.";
504 return false; 499 return false;
505 } 500 }
506 *video_frame = static_cast<VideoFrame*>(av_frame_->opaque); 501 *video_frame = static_cast<VideoFrame*>(av_frame_->opaque);
507 502
508 if (frame_rate_numerator_ == 0) {
509 // A framerate of zero indicates that no timing information was available
510 // during initial stream demuxing, and that the framerate should be inferred
511 // from the first frame's duration.
512 frame_rate_numerator_ = buffer->GetDuration().InMicroseconds();
513 frame_rate_denominator_ = base::Time::kMicrosecondsPerSecond;
514 }
515
516 // Determine timestamp and calculate the duration based on the repeat
517 // picture count. According to FFmpeg docs, the total duration can be
518 // calculated as follows:
519 // fps = 1 / time_base
520 //
521 // duration = (1 / fps) + (repeat_pict) / (2 * fps)
522 // = (2 + repeat_pict) / (2 * fps)
523 // = (2 + repeat_pict) / (2 * (1 / time_base))
524 DCHECK_LE(av_frame_->repeat_pict, 2); // Sanity check.
525 AVRational doubled_time_base;
526 doubled_time_base.num = frame_rate_denominator_;
527 doubled_time_base.den = frame_rate_numerator_ * 2;
528
529 (*video_frame)->SetTimestamp( 503 (*video_frame)->SetTimestamp(
530 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque)); 504 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque));
531 (*video_frame)->SetDuration(
532 ConvertFromTimeBase(doubled_time_base, 2 + av_frame_->repeat_pict));
533 505
534 return true; 506 return true;
535 } 507 }
536 508
537 void FFmpegVideoDecoder::ReleaseFFmpegResources() { 509 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
538 if (codec_context_) { 510 if (codec_context_) {
539 av_free(codec_context_->extradata); 511 av_free(codec_context_->extradata);
540 avcodec_close(codec_context_); 512 avcodec_close(codec_context_);
541 av_free(codec_context_); 513 av_free(codec_context_);
542 codec_context_ = NULL; 514 codec_context_ = NULL;
543 } 515 }
544 if (av_frame_) { 516 if (av_frame_) {
545 av_free(av_frame_); 517 av_free(av_frame_);
546 av_frame_ = NULL; 518 av_frame_ = NULL;
547 } 519 }
548 } 520 }
549 521
550 } // namespace media 522 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_demuxer_unittest.cc ('k') | media/filters/ffmpeg_video_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698