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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 // Available frame is guaranteed, because we issue as much reads as | 276 // Available frame is guaranteed, because we issue as much reads as |
272 // available frame, except the case of |frame_decoded| == 0, which | 277 // available frame, except the case of |frame_decoded| == 0, which |
273 // implies decoder order delay, and force us to read more inputs. | 278 // implies decoder order delay, and force us to read more inputs. |
274 DCHECK(frame_queue_available_.size()); | 279 DCHECK(frame_queue_available_.size()); |
275 video_frame = frame_queue_available_.front(); | 280 video_frame = frame_queue_available_.front(); |
276 frame_queue_available_.pop_front(); | 281 frame_queue_available_.pop_front(); |
277 | 282 |
278 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame | 283 // Copy the frame data since FFmpeg reuses internal buffers for AVFrame |
279 // output, meaning the data is only valid until the next | 284 // output, meaning the data is only valid until the next |
280 // avcodec_decode_video() call. | 285 // avcodec_decode_video() call. |
281 CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get()); | 286 size_t height = codec_context_->height; |
282 CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get()); | 287 CopyPlane(VideoFrame::kYPlane, video_frame.get(), av_frame_.get(), height); |
283 CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get()); | 288 CopyPlane(VideoFrame::kUPlane, video_frame.get(), av_frame_.get(), height); |
| 289 CopyPlane(VideoFrame::kVPlane, video_frame.get(), av_frame_.get(), height); |
284 } else { | 290 } else { |
285 // Get the VideoFrame from allocator which associate with av_frame_. | 291 // Get the VideoFrame from allocator which associate with av_frame_. |
286 video_frame = allocator_->DecodeDone(codec_context_, av_frame_.get()); | 292 video_frame = allocator_->DecodeDone(codec_context_, av_frame_.get()); |
287 } | 293 } |
288 | 294 |
289 video_frame->SetTimestamp(timestamp); | 295 video_frame->SetTimestamp(timestamp); |
290 video_frame->SetDuration(duration); | 296 video_frame->SetDuration(duration); |
291 | 297 |
292 pending_output_buffers_--; | 298 pending_output_buffers_--; |
293 event_handler_->ConsumeVideoFrame(video_frame); | 299 event_handler_->ConsumeVideoFrame(video_frame); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 // TODO(scherkus): More formats here? | 360 // TODO(scherkus): More formats here? |
355 return VideoFrame::INVALID; | 361 return VideoFrame::INVALID; |
356 } | 362 } |
357 } | 363 } |
358 | 364 |
359 } // namespace media | 365 } // namespace media |
360 | 366 |
361 // Disable refcounting for this object because this object only lives | 367 // Disable refcounting for this object because this object only lives |
362 // on the video decoder thread and there's no need to refcount it. | 368 // on the video decoder thread and there's no need to refcount it. |
363 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); | 369 DISABLE_RUNNABLE_METHOD_REFCOUNT(media::FFmpegVideoDecodeEngine); |
OLD | NEW |