OLD | NEW |
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/video_decoder_impl.h" | 5 #include "media/filters/video_decoder_impl.h" |
6 | 6 |
7 #include "base/task.h" | 7 #include "base/task.h" |
8 #include "media/base/filters.h" | 8 #include "media/base/filters.h" |
9 #include "media/base/limits.h" | 9 #include "media/base/limits.h" |
10 #include "media/base/video_frame_impl.h" | 10 #include "media/base/video_frame.h" |
11 #include "media/ffmpeg/ffmpeg_common.h" | 11 #include "media/ffmpeg/ffmpeg_common.h" |
12 #include "media/filters/ffmpeg_interfaces.h" | 12 #include "media/filters/ffmpeg_interfaces.h" |
13 #include "media/filters/video_decode_engine.h" | 13 #include "media/filters/video_decode_engine.h" |
14 #include "media/ffmpeg/ffmpeg_util.h" | 14 #include "media/ffmpeg/ffmpeg_util.h" |
15 | 15 |
16 namespace media { | 16 namespace media { |
17 | 17 |
18 VideoDecoderImpl::VideoDecoderImpl(VideoDecodeEngine* engine) | 18 VideoDecoderImpl::VideoDecoderImpl(VideoDecodeEngine* engine) |
19 : width_(0), | 19 : width_(0), |
20 height_(0), | 20 height_(0), |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 } else { | 188 } else { |
189 // When in kFlushCodec, any errored decode, or a 0-lengthed frame, | 189 // When in kFlushCodec, any errored decode, or a 0-lengthed frame, |
190 // is taken as a signal to stop decoding. | 190 // is taken as a signal to stop decoding. |
191 if (state_ == kFlushCodec) { | 191 if (state_ == kFlushCodec) { |
192 state_ = kDecodeFinished; | 192 state_ = kDecodeFinished; |
193 EnqueueEmptyFrame(); | 193 EnqueueEmptyFrame(); |
194 } | 194 } |
195 } | 195 } |
196 } | 196 } |
197 | 197 |
198 bool VideoDecoderImpl::EnqueueVideoFrame(VideoSurface::Format surface_format, | 198 bool VideoDecoderImpl::EnqueueVideoFrame(VideoFrame::Format surface_format, |
199 const TimeTuple& time, | 199 const TimeTuple& time, |
200 const AVFrame* frame) { | 200 const AVFrame* frame) { |
201 // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675 | 201 // TODO(fbarchard): Work around for FFmpeg http://crbug.com/27675 |
202 // The decoder is in a bad state and not decoding correctly. | 202 // The decoder is in a bad state and not decoding correctly. |
203 // Checking for NULL avoids a crash in CopyPlane(). | 203 // Checking for NULL avoids a crash in CopyPlane(). |
204 if (!frame->data[VideoSurface::kYPlane] || | 204 if (!frame->data[VideoFrame::kYPlane] || |
205 !frame->data[VideoSurface::kUPlane] || | 205 !frame->data[VideoFrame::kUPlane] || |
206 !frame->data[VideoSurface::kVPlane]) { | 206 !frame->data[VideoFrame::kVPlane]) { |
207 return true; | 207 return true; |
208 } | 208 } |
209 | 209 |
210 scoped_refptr<VideoFrame> video_frame; | 210 scoped_refptr<VideoFrame> video_frame; |
211 VideoFrameImpl::CreateFrame(surface_format, width_, height_, | 211 VideoFrame::CreateFrame(surface_format, width_, height_, |
212 time.timestamp, time.duration, &video_frame); | 212 time.timestamp, time.duration, &video_frame); |
213 if (!video_frame) { | 213 if (!video_frame) { |
214 return false; | 214 return false; |
215 } | 215 } |
216 | 216 |
217 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame | 217 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame |
218 // output, meaning the data is only valid until the next | 218 // output, meaning the data is only valid until the next |
219 // avcodec_decode_video() call. | 219 // avcodec_decode_video() call. |
220 // TODO(scherkus): figure out pre-allocation/buffer cycling scheme. | 220 // TODO(scherkus): figure out pre-allocation/buffer cycling scheme. |
221 // TODO(scherkus): is there a cleaner way to figure out the # of planes? | 221 // TODO(scherkus): is there a cleaner way to figure out the # of planes? |
222 VideoSurface surface; | 222 CopyPlane(VideoFrame::kYPlane, *video_frame, frame); |
223 if (!video_frame->Lock(&surface)) { | 223 CopyPlane(VideoFrame::kUPlane, *video_frame, frame); |
224 return false; | 224 CopyPlane(VideoFrame::kVPlane, *video_frame, frame); |
225 } | |
226 CopyPlane(VideoSurface::kYPlane, surface, frame); | |
227 CopyPlane(VideoSurface::kUPlane, surface, frame); | |
228 CopyPlane(VideoSurface::kVPlane, surface, frame); | |
229 video_frame->Unlock(); | |
230 EnqueueResult(video_frame); | 225 EnqueueResult(video_frame); |
231 return true; | 226 return true; |
232 } | 227 } |
233 | 228 |
234 void VideoDecoderImpl::CopyPlane(size_t plane, | 229 void VideoDecoderImpl::CopyPlane(size_t plane, |
235 const VideoSurface& surface, | 230 const VideoFrame& video_frame, |
236 const AVFrame* frame) { | 231 const AVFrame* frame) { |
237 DCHECK(surface.width % 2 == 0); | 232 DCHECK(video_frame.width() % 2 == 0); |
238 const uint8* source = frame->data[plane]; | 233 const uint8* source = frame->data[plane]; |
239 const size_t source_stride = frame->linesize[plane]; | 234 const size_t source_stride = frame->linesize[plane]; |
240 uint8* dest = surface.data[plane]; | 235 uint8* dest = video_frame.data(plane); |
241 const size_t dest_stride = surface.strides[plane]; | 236 const size_t dest_stride = video_frame.stride(plane); |
242 size_t bytes_per_line = surface.width; | 237 size_t bytes_per_line = video_frame.width(); |
243 size_t copy_lines = surface.height; | 238 size_t copy_lines = video_frame.height(); |
244 if (plane != VideoSurface::kYPlane) { | 239 if (plane != VideoFrame::kYPlane) { |
245 bytes_per_line /= 2; | 240 bytes_per_line /= 2; |
246 if (surface.format == VideoSurface::YV12) { | 241 if (video_frame.format() == VideoFrame::YV12) { |
247 copy_lines = (copy_lines + 1) / 2; | 242 copy_lines = (copy_lines + 1) / 2; |
248 } | 243 } |
249 } | 244 } |
250 DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride); | 245 DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride); |
251 for (size_t i = 0; i < copy_lines; ++i) { | 246 for (size_t i = 0; i < copy_lines; ++i) { |
252 memcpy(dest, source, bytes_per_line); | 247 memcpy(dest, source, bytes_per_line); |
253 source += source_stride; | 248 source += source_stride; |
254 dest += dest_stride; | 249 dest += dest_stride; |
255 } | 250 } |
256 } | 251 } |
257 | 252 |
258 void VideoDecoderImpl::EnqueueEmptyFrame() { | 253 void VideoDecoderImpl::EnqueueEmptyFrame() { |
259 scoped_refptr<VideoFrame> video_frame; | 254 scoped_refptr<VideoFrame> video_frame; |
260 VideoFrameImpl::CreateEmptyFrame(&video_frame); | 255 VideoFrame::CreateEmptyFrame(&video_frame); |
261 EnqueueResult(video_frame); | 256 EnqueueResult(video_frame); |
262 } | 257 } |
263 | 258 |
264 VideoDecoderImpl::TimeTuple VideoDecoderImpl::FindPtsAndDuration( | 259 VideoDecoderImpl::TimeTuple VideoDecoderImpl::FindPtsAndDuration( |
265 const AVRational& time_base, | 260 const AVRational& time_base, |
266 const PtsHeap& pts_heap, | 261 const PtsHeap& pts_heap, |
267 const TimeTuple& last_pts, | 262 const TimeTuple& last_pts, |
268 const AVFrame* frame) { | 263 const AVFrame* frame) { |
269 TimeTuple pts; | 264 TimeTuple pts; |
270 | 265 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 host()->SetError(PIPELINE_ERROR_DECODE); | 303 host()->SetError(PIPELINE_ERROR_DECODE); |
309 state_ = kDecodeFinished; | 304 state_ = kDecodeFinished; |
310 } | 305 } |
311 | 306 |
312 void VideoDecoderImpl::SetVideoDecodeEngineForTest( | 307 void VideoDecoderImpl::SetVideoDecodeEngineForTest( |
313 VideoDecodeEngine* engine) { | 308 VideoDecodeEngine* engine) { |
314 decode_engine_.reset(engine); | 309 decode_engine_.reset(engine); |
315 } | 310 } |
316 | 311 |
317 } // namespace media | 312 } // namespace media |
OLD | NEW |