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/video/ffmpeg_video_decode_engine.h" | 5 #include "media/video/ffmpeg_video_decode_engine.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/string_number_conversions.h" | 8 #include "base/string_number_conversions.h" |
9 #include "base/task.h" | 9 #include "base/task.h" |
10 #include "media/base/buffers.h" | 10 #include "media/base/buffers.h" |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 avcodec_thread_init(codec_context_, decode_threads) >= 0 && | 120 avcodec_thread_init(codec_context_, decode_threads) >= 0 && |
121 avcodec_open(codec_context_, codec) >= 0 && | 121 avcodec_open(codec_context_, codec) >= 0 && |
122 av_frame_.get() && | 122 av_frame_.get() && |
123 buffer_allocated) { | 123 buffer_allocated) { |
124 info.success = true; | 124 info.success = true; |
125 } | 125 } |
126 event_handler_ = event_handler; | 126 event_handler_ = event_handler; |
127 event_handler_->OnInitializeComplete(info); | 127 event_handler_->OnInitializeComplete(info); |
128 } | 128 } |
129 | 129 |
130 // TODO(fbarchard): Find way to remove this memcpy of the entire image. | 130 // TODO(scherkus): Move this function to a utility class and unit test. |
131 static void CopyPlane(size_t plane, | 131 static void CopyPlane(size_t plane, |
132 scoped_refptr<VideoFrame> video_frame, | 132 scoped_refptr<VideoFrame> video_frame, |
133 const AVFrame* frame) { | 133 const AVFrame* frame, |
| 134 size_t source_height) { |
134 DCHECK_EQ(video_frame->width() % 2, 0u); | 135 DCHECK_EQ(video_frame->width() % 2, 0u); |
135 const uint8* source = frame->data[plane]; | 136 const uint8* source = frame->data[plane]; |
136 const size_t source_stride = frame->linesize[plane]; | 137 const size_t source_stride = frame->linesize[plane]; |
137 uint8* dest = video_frame->data(plane); | 138 uint8* dest = video_frame->data(plane); |
138 const size_t dest_stride = video_frame->stride(plane); | 139 const size_t dest_stride = video_frame->stride(plane); |
| 140 |
| 141 // Calculate amounts to copy and clamp to minium frame dimensions. |
139 size_t bytes_per_line = video_frame->width(); | 142 size_t bytes_per_line = video_frame->width(); |
140 size_t copy_lines = video_frame->height(); | 143 size_t copy_lines = std::min(video_frame->height(), source_height); |
141 if (plane != VideoFrame::kYPlane) { | 144 if (plane != VideoFrame::kYPlane) { |
142 bytes_per_line /= 2; | 145 bytes_per_line /= 2; |
143 if (video_frame->format() == VideoFrame::YV12) { | 146 if (video_frame->format() == VideoFrame::YV12) { |
144 copy_lines = (copy_lines + 1) / 2; | 147 copy_lines = (copy_lines + 1) / 2; |
145 } | 148 } |
146 } | 149 } |
147 DCHECK(bytes_per_line <= source_stride && bytes_per_line <= dest_stride); | 150 bytes_per_line = std::min(bytes_per_line, source_stride); |
| 151 |
| 152 // Copy! |
148 for (size_t i = 0; i < copy_lines; ++i) { | 153 for (size_t i = 0; i < copy_lines; ++i) { |
149 memcpy(dest, source, bytes_per_line); | 154 memcpy(dest, source, bytes_per_line); |
150 source += source_stride; | 155 source += source_stride; |
151 dest += dest_stride; | 156 dest += dest_stride; |
152 } | 157 } |
153 } | 158 } |
154 | 159 |
155 void FFmpegVideoDecodeEngine::ConsumeVideoSample( | 160 void FFmpegVideoDecodeEngine::ConsumeVideoSample( |
156 scoped_refptr<Buffer> buffer) { | 161 scoped_refptr<Buffer> buffer) { |
157 pending_input_buffers_--; | 162 pending_input_buffers_--; |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 // Available frame is guaranteed, because we issue as much reads as | 278 // Available frame is guaranteed, because we issue as much reads as |
274 // available frame, except the case of |frame_decoded| == 0, which | 279 // available frame, except the case of |frame_decoded| == 0, which |
275 // implies decoder order delay, and force us to read more inputs. | 280 // implies decoder order delay, and force us to read more inputs. |
276 DCHECK(frame_queue_available_.size()); | 281 DCHECK(frame_queue_available_.size()); |
277 video_frame = frame_queue_available_.front(); | 282 video_frame = frame_queue_available_.front(); |
278 frame_queue_available_.pop_front(); | 283 frame_queue_available_.pop_front(); |
279 | 284 |
280 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame | 285 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame |
281 // output, meaning the data is only valid until the next | 286 // output, meaning the data is only valid until the next |
282 // avcodec_decode_video() call. | 287 // avcodec_decode_video() call. |
283 CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get()); | 288 size_t height = codec_context_->height; |
284 CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get()); | 289 CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get(), height); |
285 CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get()); | 290 CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get(), height); |
| 291 CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get(), height); |
286 } else { | 292 } else { |
287 // Get the VideoFrame from allocator which associate with av_frame_. | 293 // Get the VideoFrame from allocator which associate with av_frame_. |
288 video_frame = allocator_->DecodeDone(codec_context_, av_frame_.get()); | 294 video_frame = allocator_->DecodeDone(codec_context_, av_frame_.get()); |
289 } | 295 } |
290 | 296 |
291 video_frame->SetTimestamp(timestamp); | 297 video_frame->SetTimestamp(timestamp); |
292 video_frame->SetDuration(duration); | 298 video_frame->SetDuration(duration); |
293 | 299 |
294 pending_output_buffers_--; | 300 pending_output_buffers_--; |
295 event_handler_->ConsumeVideoFrame(video_frame); | 301 event_handler_->ConsumeVideoFrame(video_frame); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 // TODO(scherkus): More formats here? | 362 // TODO(scherkus): More formats here? |
357 return VideoFrame::INVALID; | 363 return VideoFrame::INVALID; |
358 } | 364 } |
359 } | 365 } |
360 | 366 |
361 } // namespace media | 367 } // namespace media |
362 | 368 |
363 // Disable refcounting for this object because this object only lives | 369 // Disable refcounting for this object because this object only lives |
364 // on the video decoder thread and there's no need to refcount it. | 370 // on the video decoder thread and there's no need to refcount it. |
365 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); | 371 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); |
OLD | NEW |