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

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

Issue 17408005: Refactored DecoderBuffer to use unix_hacker_style naming. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@localrefactor
Patch Set: fixed remaining style issues Created 7 years, 6 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
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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 return decode_threads; 55 return decode_threads;
56 } 56 }
57 57
58 FFmpegVideoDecoder::FFmpegVideoDecoder( 58 FFmpegVideoDecoder::FFmpegVideoDecoder(
59 const scoped_refptr<base::MessageLoopProxy>& message_loop) 59 const scoped_refptr<base::MessageLoopProxy>& message_loop)
60 : message_loop_(message_loop), 60 : message_loop_(message_loop),
61 weak_factory_(this), 61 weak_factory_(this),
62 state_(kUninitialized), 62 state_(kUninitialized),
63 codec_context_(NULL), 63 codec_context_(NULL),
64 av_frame_(NULL), 64 av_frame_(NULL),
65 demuxer_stream_(NULL) { 65 demuxer_stream_(NULL) {}
66 }
67 66
68 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context, 67 int FFmpegVideoDecoder::GetVideoBuffer(AVCodecContext* codec_context,
69 AVFrame* frame) { 68 AVFrame* frame) {
70 // Don't use |codec_context_| here! With threaded decoding, 69 // Don't use |codec_context_| here! With threaded decoding,
71 // it will contain unsynchronized width/height/pix_fmt values, 70 // it will contain unsynchronized width/height/pix_fmt values,
72 // whereas |codec_context| contains the current threads's 71 // whereas |codec_context| contains the current threads's
73 // updated width/height/pix_fmt, which can change for adaptive 72 // updated width/height/pix_fmt, which can change for adaptive
74 // content. 73 // content.
75 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt); 74 VideoFrame::Format format = PixelFormatToVideoFormat(codec_context->pix_fmt);
76 if (format == VideoFrame::INVALID) 75 if (format == VideoFrame::INVALID)
77 return AVERROR(EINVAL); 76 return AVERROR(EINVAL);
78 DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16); 77 DCHECK(format == VideoFrame::YV12 || format == VideoFrame::YV16);
79 78
80 gfx::Size size(codec_context->width, codec_context->height); 79 gfx::Size size(codec_context->width, codec_context->height);
81 int ret; 80 int ret;
82 if ((ret = av_image_check_size(size.width(), size.height(), 0, NULL)) < 0) 81 if ((ret = av_image_check_size(size.width(), size.height(), 0, NULL)) < 0)
83 return ret; 82 return ret;
84 83
85 gfx::Size natural_size; 84 gfx::Size natural_size;
86 if (codec_context->sample_aspect_ratio.num > 0) { 85 if (codec_context->sample_aspect_ratio.num > 0) {
87 natural_size = GetNaturalSize(size, 86 natural_size = GetNaturalSize(size, codec_context->sample_aspect_ratio.num,
88 codec_context->sample_aspect_ratio.num,
89 codec_context->sample_aspect_ratio.den); 87 codec_context->sample_aspect_ratio.den);
90 } else { 88 } else {
91 natural_size = demuxer_stream_->video_decoder_config().natural_size(); 89 natural_size = demuxer_stream_->video_decoder_config().natural_size();
92 } 90 }
93 91
94 if (!VideoFrame::IsValidConfig(format, size, gfx::Rect(size), natural_size)) 92 if (!VideoFrame::IsValidConfig(format, size, gfx::Rect(size), natural_size))
95 return AVERROR(EINVAL); 93 return AVERROR(EINVAL);
96 94
97 scoped_refptr<VideoFrame> video_frame = 95 scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateFrame(
98 VideoFrame::CreateFrame(format, size, gfx::Rect(size), natural_size, 96 format, size, gfx::Rect(size), natural_size, kNoTimestamp());
99 kNoTimestamp());
100 97
101 for (int i = 0; i < 3; i++) { 98 for (int i = 0; i < 3; i++) {
102 frame->base[i] = video_frame->data(i); 99 frame->base[i] = video_frame->data(i);
103 frame->data[i] = video_frame->data(i); 100 frame->data[i] = video_frame->data(i);
104 frame->linesize[i] = video_frame->stride(i); 101 frame->linesize[i] = video_frame->stride(i);
105 } 102 }
106 103
107 frame->opaque = NULL; 104 frame->opaque = NULL;
108 video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque)); 105 video_frame.swap(reinterpret_cast<VideoFrame**>(&frame->opaque));
109 frame->type = FF_BUFFER_TYPE_USER; 106 frame->type = FF_BUFFER_TYPE_USER;
110 frame->pkt_pts = codec_context->pkt ? codec_context->pkt->pts : 107 frame->pkt_pts =
111 AV_NOPTS_VALUE; 108 codec_context->pkt ? codec_context->pkt->pts : AV_NOPTS_VALUE;
112 frame->width = codec_context->width; 109 frame->width = codec_context->width;
113 frame->height = codec_context->height; 110 frame->height = codec_context->height;
114 frame->format = codec_context->pix_fmt; 111 frame->format = codec_context->pix_fmt;
115 112
116 return 0; 113 return 0;
117 } 114 }
118 115
119 static int GetVideoBufferImpl(AVCodecContext* s, AVFrame* frame) { 116 static int GetVideoBufferImpl(AVCodecContext* s, AVFrame* frame) {
120 FFmpegVideoDecoder* vd = static_cast<FFmpegVideoDecoder*>(s->opaque); 117 FFmpegVideoDecoder* vd = static_cast<FFmpegVideoDecoder*>(s->opaque);
121 return vd->GetVideoBuffer(s, frame); 118 return vd->GetVideoBuffer(s, frame);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 DCHECK(!codec_context_); 213 DCHECK(!codec_context_);
217 DCHECK(!av_frame_); 214 DCHECK(!av_frame_);
218 } 215 }
219 216
220 void FFmpegVideoDecoder::ReadFromDemuxerStream() { 217 void FFmpegVideoDecoder::ReadFromDemuxerStream() {
221 DCHECK_NE(state_, kUninitialized); 218 DCHECK_NE(state_, kUninitialized);
222 DCHECK_NE(state_, kDecodeFinished); 219 DCHECK_NE(state_, kDecodeFinished);
223 DCHECK_NE(state_, kError); 220 DCHECK_NE(state_, kError);
224 DCHECK(!read_cb_.is_null()); 221 DCHECK(!read_cb_.is_null());
225 222
226 demuxer_stream_->Read(base::Bind( 223 demuxer_stream_->Read(
227 &FFmpegVideoDecoder::BufferReady, weak_this_)); 224 base::Bind(&FFmpegVideoDecoder::BufferReady, weak_this_));
228 } 225 }
229 226
230 void FFmpegVideoDecoder::BufferReady( 227 void FFmpegVideoDecoder::BufferReady(
231 DemuxerStream::Status status, 228 DemuxerStream::Status status, const scoped_refptr<DecoderBuffer>& buffer) {
232 const scoped_refptr<DecoderBuffer>& buffer) {
233 DCHECK(message_loop_->BelongsToCurrentThread()); 229 DCHECK(message_loop_->BelongsToCurrentThread());
234 DCHECK_NE(state_, kDecodeFinished); 230 DCHECK_NE(state_, kDecodeFinished);
235 DCHECK_NE(state_, kError); 231 DCHECK_NE(state_, kError);
236 DCHECK_EQ(status != DemuxerStream::kOk, !buffer.get()) << status; 232 DCHECK_EQ(status != DemuxerStream::kOk, !buffer.get()) << status;
237 233
238 if (state_ == kUninitialized) 234 if (state_ == kUninitialized)
239 return; 235 return;
240 236
241 DCHECK(!read_cb_.is_null()); 237 DCHECK(!read_cb_.is_null());
242 238
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
277 // are discarded. 273 // are discarded.
278 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2 274 // kFlushCodec: There isn't any more input data. Call avcodec_decode_video2
279 // until no more data is returned to flush out remaining 275 // until no more data is returned to flush out remaining
280 // frames. The input buffer is ignored at this point. 276 // frames. The input buffer is ignored at this point.
281 // kDecodeFinished: All calls return empty frames. 277 // kDecodeFinished: All calls return empty frames.
282 // kError: Unexpected error happened. 278 // kError: Unexpected error happened.
283 // 279 //
284 // These are the possible state transitions. 280 // These are the possible state transitions.
285 // 281 //
286 // kNormal -> kFlushCodec: 282 // kNormal -> kFlushCodec:
287 // When buffer->IsEndOfStream() is first true. 283 // When buffer->end_of_stream() is first true.
288 // kNormal -> kError: 284 // kNormal -> kError:
289 // A decoding error occurs and decoding needs to stop. 285 // A decoding error occurs and decoding needs to stop.
290 // kFlushCodec -> kDecodeFinished: 286 // kFlushCodec -> kDecodeFinished:
291 // When avcodec_decode_video2() returns 0 data. 287 // When avcodec_decode_video2() returns 0 data.
292 // kFlushCodec -> kError: 288 // kFlushCodec -> kError:
293 // When avcodec_decode_video2() errors out. 289 // When avcodec_decode_video2() errors out.
294 // (any state) -> kNormal: 290 // (any state) -> kNormal:
295 // Any time Reset() is called. 291 // Any time Reset() is called.
296 292
297 // Transition to kFlushCodec on the first end of stream buffer. 293 // Transition to kFlushCodec on the first end of stream buffer.
298 if (state_ == kNormal && buffer->IsEndOfStream()) { 294 if (state_ == kNormal && buffer->end_of_stream()) {
299 state_ = kFlushCodec; 295 state_ = kFlushCodec;
300 } 296 }
301 297
302 scoped_refptr<VideoFrame> video_frame; 298 scoped_refptr<VideoFrame> video_frame;
303 if (!Decode(buffer, &video_frame)) { 299 if (!Decode(buffer, &video_frame)) {
304 state_ = kError; 300 state_ = kError;
305 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); 301 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
306 return; 302 return;
307 } 303 }
308 304
309 // Any successful decode counts! 305 // Any successful decode counts!
310 if (!buffer->IsEndOfStream() && buffer->GetDataSize() > 0) { 306 if (!buffer->end_of_stream() && buffer->data_size() > 0) {
311 PipelineStatistics statistics; 307 PipelineStatistics statistics;
312 statistics.video_bytes_decoded = buffer->GetDataSize(); 308 statistics.video_bytes_decoded = buffer->data_size();
313 statistics_cb_.Run(statistics); 309 statistics_cb_.Run(statistics);
314 } 310 }
315 311
316 if (!video_frame.get()) { 312 if (!video_frame.get()) {
317 if (state_ == kFlushCodec) { 313 if (state_ == kFlushCodec) {
318 DCHECK(buffer->IsEndOfStream()); 314 DCHECK(buffer->end_of_stream());
319 state_ = kDecodeFinished; 315 state_ = kDecodeFinished;
320 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame()); 316 base::ResetAndReturn(&read_cb_).Run(kOk, VideoFrame::CreateEmptyFrame());
321 return; 317 return;
322 } 318 }
323 319
324 ReadFromDemuxerStream(); 320 ReadFromDemuxerStream();
325 return; 321 return;
326 } 322 }
327 323
328 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame); 324 base::ResetAndReturn(&read_cb_).Run(kOk, video_frame);
329 } 325 }
330 326
331 bool FFmpegVideoDecoder::Decode( 327 bool FFmpegVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
332 const scoped_refptr<DecoderBuffer>& buffer, 328 scoped_refptr<VideoFrame>* video_frame) {
333 scoped_refptr<VideoFrame>* video_frame) {
334 DCHECK(video_frame); 329 DCHECK(video_frame);
335 330
336 // Reset frame to default values. 331 // Reset frame to default values.
337 avcodec_get_frame_defaults(av_frame_); 332 avcodec_get_frame_defaults(av_frame_);
338 333
339 // Create a packet for input data. 334 // Create a packet for input data.
340 // Due to FFmpeg API changes we no longer have const read-only pointers. 335 // Due to FFmpeg API changes we no longer have const read-only pointers.
341 AVPacket packet; 336 AVPacket packet;
342 av_init_packet(&packet); 337 av_init_packet(&packet);
343 if (buffer->IsEndOfStream()) { 338 if (buffer->end_of_stream()) {
344 packet.data = NULL; 339 packet.data = NULL;
345 packet.size = 0; 340 packet.size = 0;
346 } else { 341 } else {
347 packet.data = const_cast<uint8*>(buffer->GetData()); 342 packet.data = const_cast<uint8*>(buffer->data());
348 packet.size = buffer->GetDataSize(); 343 packet.size = buffer->data_size();
349 344
350 // Let FFmpeg handle presentation timestamp reordering. 345 // Let FFmpeg handle presentation timestamp reordering.
351 codec_context_->reordered_opaque = buffer->GetTimestamp().InMicroseconds(); 346 codec_context_->reordered_opaque = buffer->timestamp().InMicroseconds();
352 347
353 // This is for codecs not using get_buffer to initialize 348 // This is for codecs not using get_buffer to initialize
354 // |av_frame_->reordered_opaque| 349 // |av_frame_->reordered_opaque|
355 av_frame_->reordered_opaque = codec_context_->reordered_opaque; 350 av_frame_->reordered_opaque = codec_context_->reordered_opaque;
356 } 351 }
357 352
358 int frame_decoded = 0; 353 int frame_decoded = 0;
359 int result = avcodec_decode_video2(codec_context_, 354 int result =
360 av_frame_, 355 avcodec_decode_video2(codec_context_, av_frame_, &frame_decoded, &packet);
361 &frame_decoded,
362 &packet);
363 // Log the problem if we can't decode a video frame and exit early. 356 // Log the problem if we can't decode a video frame and exit early.
364 if (result < 0) { 357 if (result < 0) {
365 LOG(ERROR) << "Error decoding video: " << buffer->AsHumanReadableString(); 358 LOG(ERROR)
359 << "Error decoding video: " << buffer->AsHumanReadableString();
366 *video_frame = NULL; 360 *video_frame = NULL;
367 return false; 361 return false;
368 } 362 }
369 363
370 // If no frame was produced then signal that more data is required to 364 // If no frame was produced then signal that more data is required to
371 // produce more frames. This can happen under two circumstances: 365 // produce more frames. This can happen under two circumstances:
372 // 1) Decoder was recently initialized/flushed 366 // 1) Decoder was recently initialized/flushed
373 // 2) End of stream was reached and all internal frames have been output 367 // 2) End of stream was reached and all internal frames have been output
374 if (frame_decoded == 0) { 368 if (frame_decoded == 0) {
375 *video_frame = NULL; 369 *video_frame = NULL;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { 439 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) {
446 ReleaseFFmpegResources(); 440 ReleaseFFmpegResources();
447 return false; 441 return false;
448 } 442 }
449 443
450 av_frame_ = avcodec_alloc_frame(); 444 av_frame_ = avcodec_alloc_frame();
451 return true; 445 return true;
452 } 446 }
453 447
454 } // namespace media 448 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698