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

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

Issue 6171009: Remove MessageLoop methods from Filter interface (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Applied more CR suggestions & removed message_loop() methods where possible. Created 9 years, 11 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/ffmpeg_video_decoder_unittest.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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 <deque> 7 #include <deque>
8 8
9 #include "base/task.h" 9 #include "base/task.h"
10 #include "media/base/callback.h" 10 #include "media/base/callback.h"
11 #include "media/base/filters.h" 11 #include "media/base/filters.h"
12 #include "media/base/filter_host.h" 12 #include "media/base/filter_host.h"
13 #include "media/base/limits.h" 13 #include "media/base/limits.h"
14 #include "media/base/media_format.h" 14 #include "media/base/media_format.h"
15 #include "media/base/video_frame.h" 15 #include "media/base/video_frame.h"
16 #include "media/ffmpeg/ffmpeg_common.h" 16 #include "media/ffmpeg/ffmpeg_common.h"
17 #include "media/ffmpeg/ffmpeg_util.h" 17 #include "media/ffmpeg/ffmpeg_util.h"
18 #include "media/filters/ffmpeg_interfaces.h" 18 #include "media/filters/ffmpeg_interfaces.h"
19 #include "media/video/ffmpeg_video_decode_engine.h" 19 #include "media/video/ffmpeg_video_decode_engine.h"
20 #include "media/video/video_decode_context.h" 20 #include "media/video/video_decode_context.h"
21 21
22 namespace media { 22 namespace media {
23 23
24 FFmpegVideoDecoder::FFmpegVideoDecoder(VideoDecodeContext* decode_context) 24 FFmpegVideoDecoder::FFmpegVideoDecoder(MessageLoop* message_loop,
25 : width_(0), 25 VideoDecodeContext* decode_context)
26 : message_loop_(message_loop),
27 width_(0),
26 height_(0), 28 height_(0),
27 time_base_(new AVRational()), 29 time_base_(new AVRational()),
28 state_(kUnInitialized), 30 state_(kUnInitialized),
29 decode_engine_(new FFmpegVideoDecodeEngine()), 31 decode_engine_(new FFmpegVideoDecodeEngine()),
30 decode_context_(decode_context) { 32 decode_context_(decode_context) {
31 memset(&info_, 0, sizeof(info_)); 33 memset(&info_, 0, sizeof(info_));
32 } 34 }
33 35
34 FFmpegVideoDecoder::~FFmpegVideoDecoder() { 36 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
35 } 37 }
36 38
37 void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream, 39 void FFmpegVideoDecoder::Initialize(DemuxerStream* demuxer_stream,
38 FilterCallback* callback) { 40 FilterCallback* callback) {
39 if (MessageLoop::current() != message_loop()) { 41 if (MessageLoop::current() != message_loop_) {
40 message_loop()->PostTask( 42 message_loop_->PostTask(
41 FROM_HERE, 43 FROM_HERE,
42 NewRunnableMethod(this, 44 NewRunnableMethod(this,
43 &FFmpegVideoDecoder::Initialize, 45 &FFmpegVideoDecoder::Initialize,
44 make_scoped_refptr(demuxer_stream), 46 make_scoped_refptr(demuxer_stream),
45 callback)); 47 callback));
46 return; 48 return;
47 } 49 }
48 50
49 DCHECK_EQ(MessageLoop::current(), message_loop()); 51 DCHECK_EQ(MessageLoop::current(), message_loop_);
50 DCHECK(!demuxer_stream_); 52 DCHECK(!demuxer_stream_);
51 DCHECK(!initialize_callback_.get()); 53 DCHECK(!initialize_callback_.get());
52 54
53 demuxer_stream_ = demuxer_stream; 55 demuxer_stream_ = demuxer_stream;
54 initialize_callback_.reset(callback); 56 initialize_callback_.reset(callback);
55 57
56 // Get the AVStream by querying for the provider interface. 58 // Get the AVStream by querying for the provider interface.
57 AVStreamProvider* av_stream_provider; 59 AVStreamProvider* av_stream_provider;
58 if (!demuxer_stream->QueryInterface(&av_stream_provider)) { 60 if (!demuxer_stream->QueryInterface(&av_stream_provider)) {
59 VideoCodecInfo info = {0}; 61 VideoCodecInfo info = {0};
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 config.codec = kCodecMPEG4; break; 93 config.codec = kCodecMPEG4; break;
92 case CODEC_ID_VP8: 94 case CODEC_ID_VP8:
93 config.codec = kCodecVP8; break; 95 config.codec = kCodecVP8; break;
94 default: 96 default:
95 NOTREACHED(); 97 NOTREACHED();
96 } 98 }
97 config.opaque_context = av_stream; 99 config.opaque_context = av_stream;
98 config.width = width_; 100 config.width = width_;
99 config.height = height_; 101 config.height = height_;
100 state_ = kInitializing; 102 state_ = kInitializing;
101 decode_engine_->Initialize(message_loop(), this, NULL, config); 103 decode_engine_->Initialize(message_loop_, this, NULL, config);
102 } 104 }
103 105
104 void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { 106 void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) {
105 DCHECK_EQ(MessageLoop::current(), message_loop()); 107 DCHECK_EQ(MessageLoop::current(), message_loop_);
106 DCHECK(initialize_callback_.get()); 108 DCHECK(initialize_callback_.get());
107 109
108 info_ = info; // Save a copy. 110 info_ = info; // Save a copy.
109 111
110 if (info.success) { 112 if (info.success) {
111 media_format_.SetAsString(MediaFormat::kMimeType, 113 media_format_.SetAsString(MediaFormat::kMimeType,
112 mime_type::kUncompressedVideo); 114 mime_type::kUncompressedVideo);
113 media_format_.SetAsInteger(MediaFormat::kWidth, width_); 115 media_format_.SetAsInteger(MediaFormat::kWidth, width_);
114 media_format_.SetAsInteger(MediaFormat::kHeight, height_); 116 media_format_.SetAsInteger(MediaFormat::kHeight, height_);
115 media_format_.SetAsInteger( 117 media_format_.SetAsInteger(
116 MediaFormat::kSurfaceType, 118 MediaFormat::kSurfaceType,
117 static_cast<int>(info.stream_info.surface_type)); 119 static_cast<int>(info.stream_info.surface_type));
118 media_format_.SetAsInteger( 120 media_format_.SetAsInteger(
119 MediaFormat::kSurfaceFormat, 121 MediaFormat::kSurfaceFormat,
120 static_cast<int>(info.stream_info.surface_format)); 122 static_cast<int>(info.stream_info.surface_format));
121 state_ = kNormal; 123 state_ = kNormal;
122 } else { 124 } else {
123 host()->SetError(PIPELINE_ERROR_DECODE); 125 host()->SetError(PIPELINE_ERROR_DECODE);
124 } 126 }
125 127
126 initialize_callback_->Run(); 128 initialize_callback_->Run();
127 initialize_callback_.reset(); 129 initialize_callback_.reset();
128 } 130 }
129 131
130 void FFmpegVideoDecoder::Stop(FilterCallback* callback) { 132 void FFmpegVideoDecoder::Stop(FilterCallback* callback) {
131 if (MessageLoop::current() != message_loop()) { 133 if (MessageLoop::current() != message_loop_) {
132 message_loop()->PostTask(FROM_HERE, 134 message_loop_->PostTask(FROM_HERE,
133 NewRunnableMethod(this, 135 NewRunnableMethod(this,
134 &FFmpegVideoDecoder::Stop, 136 &FFmpegVideoDecoder::Stop,
135 callback)); 137 callback));
136 return; 138 return;
137 } 139 }
138 140
139 DCHECK_EQ(MessageLoop::current(), message_loop()); 141 DCHECK_EQ(MessageLoop::current(), message_loop_);
140 DCHECK(!uninitialize_callback_.get()); 142 DCHECK(!uninitialize_callback_.get());
141 143
142 uninitialize_callback_.reset(callback); 144 uninitialize_callback_.reset(callback);
143 if (state_ != kUnInitialized) 145 if (state_ != kUnInitialized)
144 decode_engine_->Uninitialize(); 146 decode_engine_->Uninitialize();
145 else 147 else
146 OnUninitializeComplete(); 148 OnUninitializeComplete();
147 } 149 }
148 150
149 void FFmpegVideoDecoder::OnUninitializeComplete() { 151 void FFmpegVideoDecoder::OnUninitializeComplete() {
150 DCHECK_EQ(MessageLoop::current(), message_loop()); 152 DCHECK_EQ(MessageLoop::current(), message_loop_);
151 DCHECK(uninitialize_callback_.get()); 153 DCHECK(uninitialize_callback_.get());
152 154
153 AutoCallbackRunner done_runner(uninitialize_callback_.release()); 155 AutoCallbackRunner done_runner(uninitialize_callback_.release());
154 state_ = kStopped; 156 state_ = kStopped;
155 157
156 // TODO(jiesun): Destroy the decoder context. 158 // TODO(jiesun): Destroy the decoder context.
157 } 159 }
158 160
159 void FFmpegVideoDecoder::Pause(FilterCallback* callback) { 161 void FFmpegVideoDecoder::Pause(FilterCallback* callback) {
160 if (MessageLoop::current() != message_loop()) { 162 if (MessageLoop::current() != message_loop_) {
161 message_loop()->PostTask(FROM_HERE, 163 message_loop_->PostTask(FROM_HERE,
162 NewRunnableMethod(this, 164 NewRunnableMethod(this,
163 &FFmpegVideoDecoder::Pause, 165 &FFmpegVideoDecoder::Pause,
164 callback)); 166 callback));
165 return; 167 return;
166 } 168 }
167 169
168 AutoCallbackRunner done_runner(callback); 170 AutoCallbackRunner done_runner(callback);
169 state_ = kPausing; 171 state_ = kPausing;
170 } 172 }
171 173
172 void FFmpegVideoDecoder::Flush(FilterCallback* callback) { 174 void FFmpegVideoDecoder::Flush(FilterCallback* callback) {
173 if (MessageLoop::current() != message_loop()) { 175 if (MessageLoop::current() != message_loop_) {
174 message_loop()->PostTask(FROM_HERE, 176 message_loop_->PostTask(FROM_HERE,
175 NewRunnableMethod(this, 177 NewRunnableMethod(this,
176 &FFmpegVideoDecoder::Flush, 178 &FFmpegVideoDecoder::Flush,
177 callback)); 179 callback));
178 return; 180 return;
179 } 181 }
180 182
181 DCHECK_EQ(MessageLoop::current(), message_loop()); 183 DCHECK_EQ(MessageLoop::current(), message_loop_);
182 DCHECK(!flush_callback_.get()); 184 DCHECK(!flush_callback_.get());
183 185
184 state_ = kFlushing; 186 state_ = kFlushing;
185 187
186 FlushBuffers(); 188 FlushBuffers();
187 189
188 flush_callback_.reset(callback); 190 flush_callback_.reset(callback);
189 191
190 decode_engine_->Flush(); 192 decode_engine_->Flush();
191 } 193 }
192 194
193 void FFmpegVideoDecoder::OnFlushComplete() { 195 void FFmpegVideoDecoder::OnFlushComplete() {
194 DCHECK_EQ(MessageLoop::current(), message_loop()); 196 DCHECK_EQ(MessageLoop::current(), message_loop_);
195 DCHECK(flush_callback_.get()); 197 DCHECK(flush_callback_.get());
196 198
197 AutoCallbackRunner done_runner(flush_callback_.release()); 199 AutoCallbackRunner done_runner(flush_callback_.release());
198 200
199 // Everything in the presentation time queue is invalid, clear the queue. 201 // Everything in the presentation time queue is invalid, clear the queue.
200 while (!pts_heap_.IsEmpty()) 202 while (!pts_heap_.IsEmpty())
201 pts_heap_.Pop(); 203 pts_heap_.Pop();
202 204
203 // Mark flush operation had been done. 205 // Mark flush operation had been done.
204 state_ = kNormal; 206 state_ = kNormal;
205 } 207 }
206 208
207 void FFmpegVideoDecoder::Seek(base::TimeDelta time, 209 void FFmpegVideoDecoder::Seek(base::TimeDelta time,
208 FilterCallback* callback) { 210 FilterCallback* callback) {
209 if (MessageLoop::current() != message_loop()) { 211 if (MessageLoop::current() != message_loop_) {
210 message_loop()->PostTask(FROM_HERE, 212 message_loop_->PostTask(FROM_HERE,
211 NewRunnableMethod(this, 213 NewRunnableMethod(this,
212 &FFmpegVideoDecoder::Seek, 214 &FFmpegVideoDecoder::Seek,
213 time, 215 time,
214 callback)); 216 callback));
215 return; 217 return;
216 } 218 }
217 219
218 DCHECK_EQ(MessageLoop::current(), message_loop()); 220 DCHECK_EQ(MessageLoop::current(), message_loop_);
219 DCHECK(!seek_callback_.get()); 221 DCHECK(!seek_callback_.get());
220 222
221 seek_callback_.reset(callback); 223 seek_callback_.reset(callback);
222 decode_engine_->Seek(); 224 decode_engine_->Seek();
223 } 225 }
224 226
225 void FFmpegVideoDecoder::OnSeekComplete() { 227 void FFmpegVideoDecoder::OnSeekComplete() {
226 DCHECK_EQ(MessageLoop::current(), message_loop()); 228 DCHECK_EQ(MessageLoop::current(), message_loop_);
227 DCHECK(seek_callback_.get()); 229 DCHECK(seek_callback_.get());
228 230
229 AutoCallbackRunner done_runner(seek_callback_.release()); 231 AutoCallbackRunner done_runner(seek_callback_.release());
230 } 232 }
231 233
232 void FFmpegVideoDecoder::OnError() { 234 void FFmpegVideoDecoder::OnError() {
233 NOTIMPLEMENTED(); 235 NOTIMPLEMENTED();
234 } 236 }
235 237
236 void FFmpegVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) { 238 void FFmpegVideoDecoder::OnFormatChange(VideoStreamInfo stream_info) {
237 NOTIMPLEMENTED(); 239 NOTIMPLEMENTED();
238 } 240 }
239 241
240 void FFmpegVideoDecoder::OnReadComplete(Buffer* buffer_in) { 242 void FFmpegVideoDecoder::OnReadComplete(Buffer* buffer_in) {
241 scoped_refptr<Buffer> buffer(buffer_in); 243 scoped_refptr<Buffer> buffer(buffer_in);
242 message_loop()->PostTask( 244 message_loop_->PostTask(
243 FROM_HERE, 245 FROM_HERE,
244 NewRunnableMethod(this, 246 NewRunnableMethod(this,
245 &FFmpegVideoDecoder::OnReadCompleteTask, 247 &FFmpegVideoDecoder::OnReadCompleteTask,
246 buffer)); 248 buffer));
247 } 249 }
248 250
249 void FFmpegVideoDecoder::OnReadCompleteTask(scoped_refptr<Buffer> buffer) { 251 void FFmpegVideoDecoder::OnReadCompleteTask(scoped_refptr<Buffer> buffer) {
250 DCHECK_EQ(MessageLoop::current(), message_loop()); 252 DCHECK_EQ(MessageLoop::current(), message_loop_);
251 DCHECK_NE(state_, kStopped); // because of Flush() before Stop(). 253 DCHECK_NE(state_, kStopped); // because of Flush() before Stop().
252 254
253 // During decode, because reads are issued asynchronously, it is possible to 255 // During decode, because reads are issued asynchronously, it is possible to
254 // receive multiple end of stream buffers since each read is acked. When the 256 // receive multiple end of stream buffers since each read is acked. When the
255 // first end of stream buffer is read, FFmpeg may still have frames queued 257 // first end of stream buffer is read, FFmpeg may still have frames queued
256 // up in the decoder so we need to go through the decode loop until it stops 258 // up in the decoder so we need to go through the decode loop until it stops
257 // giving sensible data. After that, the decoder should output empty 259 // giving sensible data. After that, the decoder should output empty
258 // frames. There are three states the decoder can be in: 260 // frames. There are three states the decoder can be in:
259 // 261 //
260 // kNormal: This is the starting state. Buffers are decoded. Decode errors 262 // kNormal: This is the starting state. Buffers are decoded. Decode errors
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 // Otherwise, attempt to decode a single frame. 296 // Otherwise, attempt to decode a single frame.
295 decode_engine_->ConsumeVideoSample(buffer); 297 decode_engine_->ConsumeVideoSample(buffer);
296 } 298 }
297 299
298 const MediaFormat& FFmpegVideoDecoder::media_format() { 300 const MediaFormat& FFmpegVideoDecoder::media_format() {
299 return media_format_; 301 return media_format_;
300 } 302 }
301 303
302 void FFmpegVideoDecoder::ProduceVideoFrame( 304 void FFmpegVideoDecoder::ProduceVideoFrame(
303 scoped_refptr<VideoFrame> video_frame) { 305 scoped_refptr<VideoFrame> video_frame) {
304 if (MessageLoop::current() != message_loop()) { 306 if (MessageLoop::current() != message_loop_) {
305 message_loop()->PostTask( 307 message_loop_->PostTask(
306 FROM_HERE, 308 FROM_HERE,
307 NewRunnableMethod(this, 309 NewRunnableMethod(this,
308 &FFmpegVideoDecoder::ProduceVideoFrame, video_frame)); 310 &FFmpegVideoDecoder::ProduceVideoFrame, video_frame));
309 return; 311 return;
310 } 312 }
311 313
312 DCHECK_EQ(MessageLoop::current(), message_loop()); 314 DCHECK_EQ(MessageLoop::current(), message_loop_);
313 315
314 // Synchronized flushing before stop should prevent this. 316 // Synchronized flushing before stop should prevent this.
315 DCHECK_NE(state_, kStopped); 317 DCHECK_NE(state_, kStopped);
316 318
317 // If the decoding is finished, we just always return empty frames. 319 // If the decoding is finished, we just always return empty frames.
318 if (state_ == kDecodeFinished) { 320 if (state_ == kDecodeFinished) {
319 // Signal VideoRenderer the end of the stream event. 321 // Signal VideoRenderer the end of the stream event.
320 scoped_refptr<VideoFrame> empty_frame; 322 scoped_refptr<VideoFrame> empty_frame;
321 VideoFrame::CreateEmptyFrame(&empty_frame); 323 VideoFrame::CreateEmptyFrame(&empty_frame);
322 VideoFrameReady(empty_frame); 324 VideoFrameReady(empty_frame);
323 325
324 // Fall through, because we still need to keep record of this frame. 326 // Fall through, because we still need to keep record of this frame.
325 } 327 }
326 328
327 // Notify decode engine the available of new frame. 329 // Notify decode engine the available of new frame.
328 decode_engine_->ProduceVideoFrame(video_frame); 330 decode_engine_->ProduceVideoFrame(video_frame);
329 } 331 }
330 332
331 void FFmpegVideoDecoder::ConsumeVideoFrame( 333 void FFmpegVideoDecoder::ConsumeVideoFrame(
332 scoped_refptr<VideoFrame> video_frame) { 334 scoped_refptr<VideoFrame> video_frame) {
333 DCHECK_EQ(MessageLoop::current(), message_loop()); 335 DCHECK_EQ(MessageLoop::current(), message_loop_);
334 DCHECK_NE(state_, kStopped); 336 DCHECK_NE(state_, kStopped);
335 337
336 if (video_frame.get()) { 338 if (video_frame.get()) {
337 if (kPausing == state_ || kFlushing == state_) { 339 if (kPausing == state_ || kFlushing == state_) {
338 frame_queue_flushed_.push_back(video_frame); 340 frame_queue_flushed_.push_back(video_frame);
339 if (kFlushing == state_) 341 if (kFlushing == state_)
340 FlushBuffers(); 342 FlushBuffers();
341 return; 343 return;
342 } 344 }
343 345
(...skipping 14 matching lines...) Expand all
358 // Signal VideoRenderer the end of the stream event. 360 // Signal VideoRenderer the end of the stream event.
359 scoped_refptr<VideoFrame> video_frame; 361 scoped_refptr<VideoFrame> video_frame;
360 VideoFrame::CreateEmptyFrame(&video_frame); 362 VideoFrame::CreateEmptyFrame(&video_frame);
361 VideoFrameReady(video_frame); 363 VideoFrameReady(video_frame);
362 } 364 }
363 } 365 }
364 } 366 }
365 367
366 void FFmpegVideoDecoder::ProduceVideoSample( 368 void FFmpegVideoDecoder::ProduceVideoSample(
367 scoped_refptr<Buffer> buffer) { 369 scoped_refptr<Buffer> buffer) {
368 DCHECK_EQ(MessageLoop::current(), message_loop()); 370 DCHECK_EQ(MessageLoop::current(), message_loop_);
369 DCHECK_NE(state_, kStopped); 371 DCHECK_NE(state_, kStopped);
370 372
371 demuxer_stream_->Read( 373 demuxer_stream_->Read(
372 NewCallback(this, &FFmpegVideoDecoder::OnReadComplete)); 374 NewCallback(this, &FFmpegVideoDecoder::OnReadComplete));
373 } 375 }
374 376
375 FFmpegVideoDecoder::TimeTuple FFmpegVideoDecoder::FindPtsAndDuration( 377 FFmpegVideoDecoder::TimeTuple FFmpegVideoDecoder::FindPtsAndDuration(
376 const AVRational& time_base, 378 const AVRational& time_base,
377 PtsHeap* pts_heap, 379 PtsHeap* pts_heap,
378 const TimeTuple& last_pts, 380 const TimeTuple& last_pts,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 VideoFrameReady(video_frame); 442 VideoFrameReady(video_frame);
441 } 443 }
442 } 444 }
443 445
444 void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( 446 void FFmpegVideoDecoder::SetVideoDecodeEngineForTest(
445 VideoDecodeEngine* engine) { 447 VideoDecodeEngine* engine) {
446 decode_engine_.reset(engine); 448 decode_engine_.reset(engine);
447 } 449 }
448 450
449 } // namespace media 451 } // namespace media
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_video_decoder.h ('k') | media/filters/ffmpeg_video_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698