OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/video/ffmpeg_video_decode_engine.h" | 5 #include "media/video/ffmpeg_video_decode_engine.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
9 #include "base/task.h" | 9 #include "base/task.h" |
10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 // decoding thread, FFmpeg treats having one thread the same as having zero | 51 // decoding thread, FFmpeg treats having one thread the same as having zero |
52 // threads (i.e., avcodec_decode_video() will execute on the calling thread). | 52 // threads (i.e., avcodec_decode_video() will execute on the calling thread). |
53 // Yet another reason for having two threads :) | 53 // Yet another reason for having two threads :) |
54 static const int kDecodeThreads = 2; | 54 static const int kDecodeThreads = 2; |
55 static const int kMaxDecodeThreads = 16; | 55 static const int kMaxDecodeThreads = 16; |
56 | 56 |
57 // Initialize AVCodecContext structure. | 57 // Initialize AVCodecContext structure. |
58 codec_context_ = avcodec_alloc_context(); | 58 codec_context_ = avcodec_alloc_context(); |
59 | 59 |
60 // TODO(scherkus): should video format get passed in via VideoDecoderConfig? | 60 // TODO(scherkus): should video format get passed in via VideoDecoderConfig? |
61 codec_context_->pix_fmt = PIX_FMT_YUV420P; | 61 // (shadi): yes! YV16 and Y12 have different memory format. |
scherkus (not reviewing)
2011/09/28 17:32:17
haha!
if these TODOs are sufficiently addressed t
shadi1
2011/09/29 18:31:03
Done.
| |
62 codec_context_->pix_fmt = config.pix_fmt(); | |
62 codec_context_->codec_type = AVMEDIA_TYPE_VIDEO; | 63 codec_context_->codec_type = AVMEDIA_TYPE_VIDEO; |
63 codec_context_->codec_id = VideoCodecToCodecID(config.codec()); | 64 codec_context_->codec_id = VideoCodecToCodecID(config.codec()); |
64 codec_context_->coded_width = config.coded_size().width(); | 65 codec_context_->coded_width = config.coded_size().width(); |
65 codec_context_->coded_height = config.coded_size().height(); | 66 codec_context_->coded_height = config.coded_size().height(); |
66 | 67 |
67 frame_rate_numerator_ = config.frame_rate_numerator(); | 68 frame_rate_numerator_ = config.frame_rate_numerator(); |
68 frame_rate_denominator_ = config.frame_rate_denominator(); | 69 frame_rate_denominator_ = config.frame_rate_denominator(); |
69 | 70 |
70 if (config.extra_data() != NULL) { | 71 if (config.extra_data() != NULL) { |
71 codec_context_->extradata_size = config.extra_data_size(); | 72 codec_context_->extradata_size = config.extra_data_size(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 VideoCodecInfo info; | 106 VideoCodecInfo info; |
106 info.success = false; | 107 info.success = false; |
107 info.natural_size = config.natural_size(); | 108 info.natural_size = config.natural_size(); |
108 | 109 |
109 // If we do not have enough buffers, we will report error too. | 110 // If we do not have enough buffers, we will report error too. |
110 frame_queue_available_.clear(); | 111 frame_queue_available_.clear(); |
111 | 112 |
112 // Create output buffer pool when direct rendering is not used. | 113 // Create output buffer pool when direct rendering is not used. |
113 for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) { | 114 for (size_t i = 0; i < Limits::kMaxVideoFrames; ++i) { |
114 scoped_refptr<VideoFrame> video_frame = | 115 scoped_refptr<VideoFrame> video_frame = |
115 VideoFrame::CreateFrame(VideoFrame::YV12, | 116 VideoFrame::CreateFrame(PixFmtToVideoFormat(codec_context_->pix_fmt), |
116 config.visible_rect().width(), | 117 config.visible_rect().width(), |
117 config.visible_rect().height(), | 118 config.visible_rect().height(), |
118 kNoTimestamp, | 119 kNoTimestamp, |
119 kNoTimestamp); | 120 kNoTimestamp); |
120 frame_queue_available_.push_back(video_frame); | 121 frame_queue_available_.push_back(video_frame); |
121 } | 122 } |
122 | 123 |
123 codec_context_->thread_count = decode_threads; | 124 codec_context_->thread_count = decode_threads; |
124 if (codec && | 125 if (codec && |
125 avcodec_open(codec_context_, codec) >= 0 && | 126 avcodec_open(codec_context_, codec) >= 0 && |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 // available frame, except the case of |frame_decoded| == 0, which | 244 // available frame, except the case of |frame_decoded| == 0, which |
244 // implies decoder order delay, and force us to read more inputs. | 245 // implies decoder order delay, and force us to read more inputs. |
245 DCHECK(frame_queue_available_.size()); | 246 DCHECK(frame_queue_available_.size()); |
246 video_frame = frame_queue_available_.front(); | 247 video_frame = frame_queue_available_.front(); |
247 frame_queue_available_.pop_front(); | 248 frame_queue_available_.pop_front(); |
248 | 249 |
249 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame | 250 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame |
250 // output, meaning the data is only valid until the next | 251 // output, meaning the data is only valid until the next |
251 // avcodec_decode_video() call. | 252 // avcodec_decode_video() call. |
252 int y_rows = codec_context_->height; | 253 int y_rows = codec_context_->height; |
253 int uv_rows = codec_context_->height / 2; | 254 int uv_rows = video_frame->rows(VideoFrame::kUPlane); |
scherkus (not reviewing)
2011/09/28 17:32:17
nice :)
| |
255 | |
254 CopyYPlane(av_frame_->data[0], av_frame_->linesize[0], y_rows, video_frame); | 256 CopyYPlane(av_frame_->data[0], av_frame_->linesize[0], y_rows, video_frame); |
255 CopyUPlane(av_frame_->data[1], av_frame_->linesize[1], uv_rows, video_frame); | 257 CopyUPlane(av_frame_->data[1], av_frame_->linesize[1], uv_rows, video_frame); |
256 CopyVPlane(av_frame_->data[2], av_frame_->linesize[2], uv_rows, video_frame); | 258 CopyVPlane(av_frame_->data[2], av_frame_->linesize[2], uv_rows, video_frame); |
257 | 259 |
258 video_frame->SetTimestamp(timestamp); | 260 video_frame->SetTimestamp(timestamp); |
259 video_frame->SetDuration(duration); | 261 video_frame->SetDuration(duration); |
260 | 262 |
261 pending_output_buffers_--; | 263 pending_output_buffers_--; |
262 event_handler_->ConsumeVideoFrame(video_frame, statistics); | 264 event_handler_->ConsumeVideoFrame(video_frame, statistics); |
263 } | 265 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 DCHECK_EQ(output_eos_reached_, false); | 302 DCHECK_EQ(output_eos_reached_, false); |
301 pending_input_buffers_++; | 303 pending_input_buffers_++; |
302 event_handler_->ProduceVideoSample(NULL); | 304 event_handler_->ProduceVideoSample(NULL); |
303 } | 305 } |
304 | 306 |
305 } // namespace media | 307 } // namespace media |
306 | 308 |
307 // Disable refcounting for this object because this object only lives | 309 // Disable refcounting for this object because this object only lives |
308 // on the video decoder thread and there's no need to refcount it. | 310 // on the video decoder thread and there's no need to refcount it. |
309 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); | 311 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); |
OLD | NEW |