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

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

Issue 60069: FFmpeg video decoder glue code... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 8 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') | no next file » | 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) 2009 The Chromium Authors. All rights reserved. Use of this 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in the 2 // source code is governed by a BSD-style license that can be found in the
3 // LICENSE file. 3 // LICENSE file.
4 4
5 #include "media/base/video_frame_impl.h"
6 #include "media/filters/ffmpeg_common.h"
7 #include "media/filters/ffmpeg_demuxer.h"
5 #include "media/filters/ffmpeg_video_decoder.h" 8 #include "media/filters/ffmpeg_video_decoder.h"
6 9
7 namespace media { 10 namespace media {
8 11
12
9 FFmpegVideoDecoder::FFmpegVideoDecoder() 13 FFmpegVideoDecoder::FFmpegVideoDecoder()
10 : DecoderBase<VideoDecoder, VideoFrame>(NULL) { 14 : DecoderBase<VideoDecoder, VideoFrame>(NULL),
11 NOTIMPLEMENTED(); 15 width_(0),
16 height_(0) {
12 } 17 }
13 18
14 FFmpegVideoDecoder::~FFmpegVideoDecoder() { 19 FFmpegVideoDecoder::~FFmpegVideoDecoder() {
15 NOTIMPLEMENTED();
16 } 20 }
17 21
18 // static 22 // static
19 bool FFmpegVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) { 23 bool FFmpegVideoDecoder::IsMediaFormatSupported(const MediaFormat& format) {
20 NOTIMPLEMENTED(); 24 std::string mime_type;
21 return false; 25 return format.GetAsString(MediaFormat::kMimeType, &mime_type) &&
26 mime_type::kFFmpegVideo == mime_type;
22 } 27 }
23 28
24 bool FFmpegVideoDecoder::OnInitialize(DemuxerStream* demuxer_stream) { 29 bool FFmpegVideoDecoder::OnInitialize(DemuxerStream* demuxer_stream) {
25 NOTIMPLEMENTED(); 30 scoped_refptr<FFmpegDemuxerStream> ffmpeg_demuxer_stream;
26 return false; 31 if (!demuxer_stream->QueryInterface(&ffmpeg_demuxer_stream)) {
32 return false;
33 }
34
35 AVStream* av_stream = ffmpeg_demuxer_stream->av_stream();
36
37 width_ = av_stream->codec->width;
38 height_ = av_stream->codec->height;
39
40 media_format_.SetAsString(MediaFormat::kMimeType,
41 mime_type::kUncompressedVideo);
42 media_format_.SetAsInteger(MediaFormat::kWidth, width_);
43 media_format_.SetAsInteger(MediaFormat::kHeight, height_);
44
45 codec_context_ = ffmpeg_demuxer_stream->av_stream()->codec;
46
47 return true;
27 } 48 }
28 49
29 void FFmpegVideoDecoder::OnDecode(Buffer* input) { 50 void FFmpegVideoDecoder::OnDecode(Buffer* buffer) {
30 NOTIMPLEMENTED(); 51 // Check for end of stream.
52 // TODO(scherkus): check for end of stream.
53
54 // Queue the incoming timestamp.
55 TimeTuple times;
56 times.timestamp = buffer->GetTimestamp();
57 times.duration = buffer->GetDuration();
58 time_queue_.push(times);
59
60 // Cast everything to FFmpeg types.
61 const uint8_t* data_in = buffer->GetData();
62 const size_t size_in = buffer->GetDataSize();
63
64 int decoded = 0;
65 AVFrame yuv_frame;
66 avcodec_get_frame_defaults(&yuv_frame);
67 int result = avcodec_decode_video(codec_context_, &yuv_frame, &decoded,
68 data_in, size_in);
69
70 if (result < 0) {
71 host_->Error(PIPELINE_ERROR_DECODE);
72 return;
73 }
74
75 if (result == 0 || decoded == 0) {
76 return;
77 }
78
79 VideoSurface::Format surface_format;
80 switch (codec_context_->pix_fmt) {
81 case PIX_FMT_YUV420P:
82 surface_format = VideoSurface::YV12;
83 break;
84 case PIX_FMT_YUV422P:
85 surface_format = VideoSurface::YV16;
86 break;
87 default:
88 // TODO(scherkus): More formats here?
89 NOTREACHED();
90 host_->Error(PIPELINE_ERROR_DECODE);
91 return;
92 }
93 if (!EnqueueVideoFrame(surface_format, yuv_frame)) {
94 host_->Error(PIPELINE_ERROR_DECODE);
95 }
96 }
97
98 bool FFmpegVideoDecoder::EnqueueVideoFrame(VideoSurface::Format surface_format,
99 const AVFrame& frame) {
100 // Dequeue the next time tuple and create a VideoFrame object with
101 // that timestamp and duration.
102 TimeTuple time = time_queue_.top();
103 time_queue_.pop();
104
105 scoped_refptr<VideoFrame> video_frame;
106 VideoFrameImpl::CreateFrame(surface_format, width_, height_,
107 time.timestamp, time.duration, &video_frame);
108 if (!video_frame) {
109 return false;
110 }
111 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame
112 // output, meaning the data is only valid until the next
113 // avcodec_decode_video() call.
114 // TODO(scherkus): figure out pre-allocation/buffer cycling scheme.
115 // TODO(scherkus): is there a cleaner way to figure out the # of planes?
116 VideoSurface surface;
117 if (!video_frame->Lock(&surface)) {
118 return false;
119 }
120 CopyPlane(VideoSurface::kYPlane, surface, frame);
121 CopyPlane(VideoSurface::kUPlane, surface, frame);
122 CopyPlane(VideoSurface::kVPlane, surface, frame);
123 video_frame->Unlock();
124 EnqueueResult(video_frame);
125 return true;
126 }
127
128 void FFmpegVideoDecoder::CopyPlane(size_t plane,
129 const VideoSurface& surface,
130 const AVFrame& frame) {
131 DCHECK(surface.width % 4 == 0);
132 DCHECK(surface.height % 2 == 0);
133 const uint8* source = frame.data[plane];
134 const size_t source_stride = frame.linesize[plane];
135 uint8* dest = surface.data[plane];
136 const size_t dest_stride = surface.strides[plane];
137 size_t bytes_per_line = surface.width;
138 size_t copy_lines = surface.height;
139 if (plane != VideoSurface::kYPlane) {
140 bytes_per_line /= 2;
141 if (surface.format == VideoSurface::YV12) {
142 copy_lines /= 2;
143 }
144 }
145 DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride);
146 for (size_t i = 0; i < copy_lines; ++i) {
147 memcpy(dest, source, bytes_per_line);
148 source += source_stride;
149 dest += dest_stride;
150 }
31 } 151 }
32 152
33 } // namespace 153 } // namespace
OLDNEW
« no previous file with comments | « media/filters/ffmpeg_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698