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

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

Issue 464113003: Add delay in FFmpegVideoDecoder::Decode(). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Less frequent but longer decode delay. Created 6 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
« no previous file with comments | « media/filters/ffmpeg_video_decoder.h ('k') | media/filters/video_renderer_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 68
69 static size_t RoundUp(size_t value, size_t alignment) { 69 static size_t RoundUp(size_t value, size_t alignment) {
70 // Check that |alignment| is a power of 2. 70 // Check that |alignment| is a power of 2.
71 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1))); 71 DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
72 return ((value + (alignment - 1)) & ~(alignment - 1)); 72 return ((value + (alignment - 1)) & ~(alignment - 1));
73 } 73 }
74 74
75 FFmpegVideoDecoder::FFmpegVideoDecoder( 75 FFmpegVideoDecoder::FFmpegVideoDecoder(
76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) 76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
77 : task_runner_(task_runner), state_(kUninitialized), 77 : task_runner_(task_runner), state_(kUninitialized),
78 decode_nalus_(false) {} 78 decode_nalus_(false), weak_factory_(this) {}
79 79
80 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context, 80 int FFmpegVideoDecoder::GetVideoBuffer(struct AVCodecContext* codec_context,
81 AVFrame* frame, 81 AVFrame* frame,
82 int flags) { 82 int flags) {
83 // Don't use |codec_context_| here! With threaded decoding, 83 // Don't use |codec_context_| here! With threaded decoding,
84 // it will contain unsynchronized width/height/pix_fmt values, 84 // it will contain unsynchronized width/height/pix_fmt values,
85 // whereas |codec_context| contains the current threads's 85 // whereas |codec_context| contains the current threads's
86 // updated width/height/pix_fmt, which can change for adaptive 86 // updated width/height/pix_fmt, which can change for adaptive
87 // content. 87 // content.
88 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt); 88 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 ReleaseVideoBufferImpl, 146 ReleaseVideoBufferImpl,
147 opaque, 147 opaque,
148 0); 148 0);
149 return 0; 149 return 0;
150 } 150 }
151 151
152 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config, 152 void FFmpegVideoDecoder::Initialize(const VideoDecoderConfig& config,
153 bool low_delay, 153 bool low_delay,
154 const PipelineStatusCB& status_cb, 154 const PipelineStatusCB& status_cb,
155 const OutputCB& output_cb) { 155 const OutputCB& output_cb) {
156 DVLOG(2) << __FUNCTION__;
156 DCHECK(task_runner_->BelongsToCurrentThread()); 157 DCHECK(task_runner_->BelongsToCurrentThread());
157 DCHECK(!config.is_encrypted()); 158 DCHECK(!config.is_encrypted());
158 DCHECK(!output_cb.is_null()); 159 DCHECK(!output_cb.is_null());
159 160
160 FFmpegGlue::InitializeFFmpeg(); 161 FFmpegGlue::InitializeFFmpeg();
161 162
162 config_ = config; 163 config_ = config;
163 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); 164 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
164 165
165 if (!config.IsValidConfig() || !ConfigureDecoder(low_delay)) { 166 if (!config.IsValidConfig() || !ConfigureDecoder(low_delay)) {
166 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); 167 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
167 return; 168 return;
168 } 169 }
169 170
170 output_cb_ = BindToCurrentLoop(output_cb); 171 output_cb_ = BindToCurrentLoop(output_cb);
171 172
172 // Success! 173 // Success!
173 state_ = kNormal; 174 state_ = kNormal;
174 initialize_cb.Run(PIPELINE_OK); 175 initialize_cb.Run(PIPELINE_OK);
175 } 176 }
176 177
177 void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, 178 void FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
178 const DecodeCB& decode_cb) { 179 const DecodeCB& decode_cb) {
180 DVLOG(2) << __FUNCTION__;
181 DCHECK(task_runner_->BelongsToCurrentThread());
182
183 static int count = 1;
184 count++;
185 int delay = 1;
186 if (count % 100 == 0)
187 delay = 2000;
188
189 //base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(delay));
190 //DecodeInternal(buffer, decode_cb);
191
192 task_runner_->PostDelayedTask(FROM_HERE,
193 base::Bind(&FFmpegVideoDecoder::DecodeInternal,
194 weak_factory_.GetWeakPtr(),
195 buffer,
196 decode_cb),
197 base::TimeDelta::FromMilliseconds(delay));
198 }
199
200 void FFmpegVideoDecoder::DecodeInternal(const scoped_refptr<DecoderBuffer>& buff er,
201 const DecodeCB& decode_cb) {
202 DVLOG(2) << __FUNCTION__;
179 DCHECK(task_runner_->BelongsToCurrentThread()); 203 DCHECK(task_runner_->BelongsToCurrentThread());
180 DCHECK(buffer); 204 DCHECK(buffer);
181 DCHECK(!decode_cb.is_null()); 205 DCHECK(!decode_cb.is_null());
182 CHECK_NE(state_, kUninitialized); 206 CHECK_NE(state_, kUninitialized);
183 207
184 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb); 208 DecodeCB decode_cb_bound = BindToCurrentLoop(decode_cb);
185 209
186 if (state_ == kError) { 210 if (state_ == kError) {
187 decode_cb_bound.Run(kDecodeError); 211 decode_cb_bound.Run(kDecodeError);
188 return; 212 return;
189 } 213 }
190 214
191 if (state_ == kDecodeFinished) { 215 if (state_ == kDecodeFinished) {
192 decode_cb_bound.Run(kOk); 216 decode_cb_bound.Run(kOk);
193 return; 217 return;
194 } 218 }
195 219
220 //base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(40));
221
196 DCHECK_EQ(state_, kNormal); 222 DCHECK_EQ(state_, kNormal);
197 223
198 // During decode, because reads are issued asynchronously, it is possible to 224 // During decode, because reads are issued asynchronously, it is possible to
199 // receive multiple end of stream buffers since each decode is acked. When the 225 // receive multiple end of stream buffers since each decode is acked. When the
200 // first end of stream buffer is read, FFmpeg may still have frames queued 226 // first end of stream buffer is read, FFmpeg may still have frames queued
201 // up in the decoder so we need to go through the decode loop until it stops 227 // up in the decoder so we need to go through the decode loop until it stops
202 // giving sensible data. After that, the decoder should output empty 228 // giving sensible data. After that, the decoder should output empty
203 // frames. There are three states the decoder can be in: 229 // frames. There are three states the decoder can be in:
204 // 230 //
205 // kNormal: This is the starting state. Buffers are decoded. Decode errors 231 // kNormal: This is the starting state. Buffers are decoded. Decode errors
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 LOG(ERROR) << "Video frame was produced yet has invalid frame data."; 327 LOG(ERROR) << "Video frame was produced yet has invalid frame data.";
302 av_frame_unref(av_frame_.get()); 328 av_frame_unref(av_frame_.get());
303 return false; 329 return false;
304 } 330 }
305 331
306 scoped_refptr<VideoFrame> frame = 332 scoped_refptr<VideoFrame> frame =
307 reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(av_frame_->buf[0])); 333 reinterpret_cast<VideoFrame*>(av_buffer_get_opaque(av_frame_->buf[0]));
308 frame->set_timestamp( 334 frame->set_timestamp(
309 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque)); 335 base::TimeDelta::FromMicroseconds(av_frame_->reordered_opaque));
310 *has_produced_frame = true; 336 *has_produced_frame = true;
337
311 output_cb_.Run(frame); 338 output_cb_.Run(frame);
312 339
313 av_frame_unref(av_frame_.get()); 340 av_frame_unref(av_frame_.get());
314 return true; 341 return true;
315 } 342 }
316 343
317 void FFmpegVideoDecoder::ReleaseFFmpegResources() { 344 void FFmpegVideoDecoder::ReleaseFFmpegResources() {
318 codec_context_.reset(); 345 codec_context_.reset();
319 av_frame_.reset(); 346 av_frame_.reset();
320 } 347 }
(...skipping 20 matching lines...) Expand all
341 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) { 368 if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
342 ReleaseFFmpegResources(); 369 ReleaseFFmpegResources();
343 return false; 370 return false;
344 } 371 }
345 372
346 av_frame_.reset(av_frame_alloc()); 373 av_frame_.reset(av_frame_alloc());
347 return true; 374 return true;
348 } 375 }
349 376
350 } // namespace media 377 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_video_decoder.h ('k') | media/filters/video_renderer_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698