| 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 |