| 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/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/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/task.h" | 10 #include "base/task.h" |
| 11 #include "media/base/callback.h" | 11 #include "media/base/callback.h" |
| 12 #include "media/base/demuxer_stream.h" | 12 #include "media/base/demuxer_stream.h" |
| 13 #include "media/base/filters.h" | 13 #include "media/base/filters.h" |
| 14 #include "media/base/filter_host.h" | 14 #include "media/base/filter_host.h" |
| 15 #include "media/base/limits.h" | 15 #include "media/base/limits.h" |
| 16 #include "media/base/video_frame.h" | 16 #include "media/base/video_frame.h" |
| 17 #include "media/ffmpeg/ffmpeg_common.h" | 17 #include "media/ffmpeg/ffmpeg_common.h" |
| 18 #include "media/video/ffmpeg_video_decode_engine.h" | 18 #include "media/video/ffmpeg_video_decode_engine.h" |
| 19 #include "media/video/video_decode_context.h" | 19 #include "media/video/video_decode_context.h" |
| 20 #include "ui/gfx/rect.h" |
| 20 | 21 |
| 21 namespace media { | 22 namespace media { |
| 22 | 23 |
| 23 FFmpegVideoDecoder::FFmpegVideoDecoder(MessageLoop* message_loop, | 24 FFmpegVideoDecoder::FFmpegVideoDecoder(MessageLoop* message_loop, |
| 24 VideoDecodeContext* decode_context) | 25 VideoDecodeContext* decode_context) |
| 25 : message_loop_(message_loop), | 26 : message_loop_(message_loop), |
| 26 state_(kUnInitialized), | 27 state_(kUnInitialized), |
| 27 decode_engine_(new FFmpegVideoDecodeEngine()), | 28 decode_engine_(new FFmpegVideoDecodeEngine()), |
| 28 decode_context_(decode_context) { | 29 decode_context_(decode_context) { |
| 29 memset(&info_, 0, sizeof(info_)); | 30 memset(&info_, 0, sizeof(info_)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 | 63 |
| 63 AVStream* av_stream = demuxer_stream->GetAVStream(); | 64 AVStream* av_stream = demuxer_stream->GetAVStream(); |
| 64 if (!av_stream) { | 65 if (!av_stream) { |
| 65 VideoCodecInfo info = {0}; | 66 VideoCodecInfo info = {0}; |
| 66 OnInitializeComplete(info); | 67 OnInitializeComplete(info); |
| 67 return; | 68 return; |
| 68 } | 69 } |
| 69 | 70 |
| 70 pts_stream_.Initialize(GetFrameDuration(av_stream)); | 71 pts_stream_.Initialize(GetFrameDuration(av_stream)); |
| 71 | 72 |
| 72 int width = av_stream->codec->coded_width; | 73 gfx::Size coded_size( |
| 73 int height = av_stream->codec->coded_height; | 74 av_stream->codec->coded_width, av_stream->codec->coded_height); |
| 75 // TODO(vrk): This assumes decoded frame data starts at (0, 0), which is true |
| 76 // for now, but may not always be true forever. Fix this in the future. |
| 77 gfx::Rect visible_rect( |
| 78 av_stream->codec->width, av_stream->codec->height); |
| 79 gfx::Size natural_size( |
| 80 GetNaturalWidth(av_stream), GetNaturalHeight(av_stream)); |
| 74 | 81 |
| 75 int surface_width = GetSurfaceWidth(av_stream); | 82 if (natural_size.width() > Limits::kMaxDimension || |
| 76 int surface_height = GetSurfaceHeight(av_stream); | 83 natural_size.height() > Limits::kMaxDimension || |
| 77 | 84 natural_size.GetArea() > Limits::kMaxCanvas) { |
| 78 if (surface_width > Limits::kMaxDimension || | |
| 79 surface_height > Limits::kMaxDimension || | |
| 80 (surface_width * surface_height) > Limits::kMaxCanvas) { | |
| 81 VideoCodecInfo info = {0}; | 85 VideoCodecInfo info = {0}; |
| 82 OnInitializeComplete(info); | 86 OnInitializeComplete(info); |
| 83 return; | 87 return; |
| 84 } | 88 } |
| 85 | 89 |
| 86 VideoDecoderConfig config(CodecIDToVideoCodec(av_stream->codec->codec_id), | 90 VideoDecoderConfig config(CodecIDToVideoCodec(av_stream->codec->codec_id), |
| 87 width, height, | 91 coded_size, visible_rect, natural_size, |
| 88 surface_width, surface_height, | |
| 89 av_stream->r_frame_rate.num, | 92 av_stream->r_frame_rate.num, |
| 90 av_stream->r_frame_rate.den, | 93 av_stream->r_frame_rate.den, |
| 91 av_stream->codec->extradata, | 94 av_stream->codec->extradata, |
| 92 av_stream->codec->extradata_size); | 95 av_stream->codec->extradata_size); |
| 93 state_ = kInitializing; | 96 state_ = kInitializing; |
| 94 decode_engine_->Initialize(message_loop_, this, NULL, config); | 97 decode_engine_->Initialize(message_loop_, this, NULL, config); |
| 95 } | 98 } |
| 96 | 99 |
| 97 void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { | 100 void FFmpegVideoDecoder::OnInitializeComplete(const VideoCodecInfo& info) { |
| 98 DCHECK_EQ(MessageLoop::current(), message_loop_); | 101 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 | 335 |
| 333 void FFmpegVideoDecoder::ProduceVideoSample( | 336 void FFmpegVideoDecoder::ProduceVideoSample( |
| 334 scoped_refptr<Buffer> buffer) { | 337 scoped_refptr<Buffer> buffer) { |
| 335 DCHECK_EQ(MessageLoop::current(), message_loop_); | 338 DCHECK_EQ(MessageLoop::current(), message_loop_); |
| 336 DCHECK_NE(state_, kStopped); | 339 DCHECK_NE(state_, kStopped); |
| 337 | 340 |
| 338 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::OnReadComplete, | 341 demuxer_stream_->Read(base::Bind(&FFmpegVideoDecoder::OnReadComplete, |
| 339 this)); | 342 this)); |
| 340 } | 343 } |
| 341 | 344 |
| 342 int FFmpegVideoDecoder::width() { | 345 gfx::Size FFmpegVideoDecoder::natural_size() { |
| 343 DCHECK(info_.success); | 346 DCHECK(info_.success); |
| 344 return info_.surface_width; | 347 return info_.natural_size; |
| 345 } | |
| 346 | |
| 347 int FFmpegVideoDecoder::height() { | |
| 348 DCHECK(info_.success); | |
| 349 return info_.surface_height; | |
| 350 } | 348 } |
| 351 | 349 |
| 352 void FFmpegVideoDecoder::FlushBuffers() { | 350 void FFmpegVideoDecoder::FlushBuffers() { |
| 353 while (!frame_queue_flushed_.empty()) { | 351 while (!frame_queue_flushed_.empty()) { |
| 354 scoped_refptr<VideoFrame> video_frame; | 352 scoped_refptr<VideoFrame> video_frame; |
| 355 video_frame = frame_queue_flushed_.front(); | 353 video_frame = frame_queue_flushed_.front(); |
| 356 frame_queue_flushed_.pop_front(); | 354 frame_queue_flushed_.pop_front(); |
| 357 | 355 |
| 358 // Return frames back to the decode engine. | 356 // Return frames back to the decode engine. |
| 359 decode_engine_->ProduceVideoFrame(video_frame); | 357 decode_engine_->ProduceVideoFrame(video_frame); |
| 360 } | 358 } |
| 361 } | 359 } |
| 362 | 360 |
| 363 void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( | 361 void FFmpegVideoDecoder::SetVideoDecodeEngineForTest( |
| 364 VideoDecodeEngine* engine) { | 362 VideoDecodeEngine* engine) { |
| 365 decode_engine_.reset(engine); | 363 decode_engine_.reset(engine); |
| 366 } | 364 } |
| 367 | 365 |
| 368 } // namespace media | 366 } // namespace media |
| OLD | NEW |