OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/vpx_video_decoder.h" | 5 #include "media/filters/vpx_video_decoder.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "media/base/video_frame.h" | 24 #include "media/base/video_frame.h" |
25 #include "media/base/video_util.h" | 25 #include "media/base/video_util.h" |
26 | 26 |
27 // Include libvpx header files. | 27 // Include libvpx header files. |
28 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide | 28 // VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide |
29 // backwards compatibility for legacy applications using the library. | 29 // backwards compatibility for legacy applications using the library. |
30 #define VPX_CODEC_DISABLE_COMPAT 1 | 30 #define VPX_CODEC_DISABLE_COMPAT 1 |
31 extern "C" { | 31 extern "C" { |
32 #include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" | 32 #include "third_party/libvpx/source/libvpx/vpx/vpx_decoder.h" |
33 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" | 33 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" |
34 #include "third_party/libvpx/source/libvpx/vpx/vpx_external_frame_buffer.h" | |
fgalligan1
2013/12/16 19:38:43
This include should be before vp8dx
vignesh
2013/12/16 21:10:57
Done.
| |
34 } | 35 } |
35 | 36 |
36 namespace media { | 37 namespace media { |
37 | 38 |
38 // Always try to use three threads for video decoding. There is little reason | 39 // Always try to use three threads for video decoding. There is little reason |
39 // not to since current day CPUs tend to be multi-core and we measured | 40 // not to since current day CPUs tend to be multi-core and we measured |
40 // performance benefits on older machines such as P4s with hyperthreading. | 41 // performance benefits on older machines such as P4s with hyperthreading. |
41 static const int kDecodeThreads = 2; | 42 static const int kDecodeThreads = 2; |
42 static const int kMaxDecodeThreads = 16; | 43 static const int kMaxDecodeThreads = 16; |
43 | 44 |
(...skipping 22 matching lines...) Expand all Loading... | |
66 decode_threads = std::min(decode_threads, kMaxDecodeThreads); | 67 decode_threads = std::min(decode_threads, kMaxDecodeThreads); |
67 return decode_threads; | 68 return decode_threads; |
68 } | 69 } |
69 | 70 |
70 VpxVideoDecoder::VpxVideoDecoder( | 71 VpxVideoDecoder::VpxVideoDecoder( |
71 const scoped_refptr<base::MessageLoopProxy>& message_loop) | 72 const scoped_refptr<base::MessageLoopProxy>& message_loop) |
72 : message_loop_(message_loop), | 73 : message_loop_(message_loop), |
73 weak_factory_(this), | 74 weak_factory_(this), |
74 state_(kUninitialized), | 75 state_(kUninitialized), |
75 vpx_codec_(NULL), | 76 vpx_codec_(NULL), |
76 vpx_codec_alpha_(NULL) { | 77 vpx_codec_alpha_(NULL), |
78 frame_buffers_(NULL) { | |
77 } | 79 } |
78 | 80 |
79 VpxVideoDecoder::~VpxVideoDecoder() { | 81 VpxVideoDecoder::~VpxVideoDecoder() { |
80 DCHECK_EQ(kUninitialized, state_); | 82 DCHECK_EQ(kUninitialized, state_); |
81 CloseDecoder(); | 83 CloseDecoder(); |
82 } | 84 } |
83 | 85 |
84 void VpxVideoDecoder::Initialize(const VideoDecoderConfig& config, | 86 void VpxVideoDecoder::Initialize(const VideoDecoderConfig& config, |
85 const PipelineStatusCB& status_cb) { | 87 const PipelineStatusCB& status_cb) { |
86 DCHECK(message_loop_->BelongsToCurrentThread()); | 88 DCHECK(message_loop_->BelongsToCurrentThread()); |
(...skipping 30 matching lines...) Expand all Loading... | |
117 &vpx_config, | 119 &vpx_config, |
118 0); | 120 0); |
119 if (status != VPX_CODEC_OK) { | 121 if (status != VPX_CODEC_OK) { |
120 LOG(ERROR) << "vpx_codec_dec_init failed, status=" << status; | 122 LOG(ERROR) << "vpx_codec_dec_init failed, status=" << status; |
121 delete context; | 123 delete context; |
122 return NULL; | 124 return NULL; |
123 } | 125 } |
124 return context; | 126 return context; |
125 } | 127 } |
126 | 128 |
129 int32 VpxVideoDecoder::ReallocVP9FrameBuffer(void *user_priv, size_t new_size, | |
130 vpx_codec_frame_buffer *fb) { | |
131 if (!fb) | |
132 return -1; | |
133 if (fb->data) | |
134 delete[] fb->data; | |
135 fb->data = new uint8[new_size]; | |
136 if (!fb->data) { | |
137 fb->size = 0; | |
138 return -1; | |
139 } | |
140 fb->size = new_size; | |
141 return VPX_CODEC_OK; | |
142 } | |
143 | |
127 bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) { | 144 bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) { |
128 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); | 145 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); |
129 bool can_handle = false; | 146 bool can_handle = false; |
130 if (config.codec() == kCodecVP9) | 147 if (config.codec() == kCodecVP9) |
131 can_handle = true; | 148 can_handle = true; |
132 if (!cmd_line->HasSwitch(switches::kDisableVp8AlphaPlayback) && | 149 if (!cmd_line->HasSwitch(switches::kDisableVp8AlphaPlayback) && |
133 config.codec() == kCodecVP8 && config.format() == VideoFrame::YV12A) { | 150 config.codec() == kCodecVP8 && config.format() == VideoFrame::YV12A) { |
134 can_handle = true; | 151 can_handle = true; |
135 } | 152 } |
136 if (!can_handle) | 153 if (!can_handle) |
137 return false; | 154 return false; |
138 | 155 |
139 CloseDecoder(); | 156 CloseDecoder(); |
140 | 157 |
141 vpx_codec_ = InitializeVpxContext(vpx_codec_, config); | 158 vpx_codec_ = InitializeVpxContext(vpx_codec_, config); |
142 if (!vpx_codec_) | 159 if (!vpx_codec_) |
143 return false; | 160 return false; |
144 | 161 |
162 // We use our own buffers for VP9 so that there is no need to copy data after | |
163 // decoding. | |
164 if (config.codec() == kCodecVP9) { | |
fgalligan1
2013/12/16 19:38:43
You are going to have to add a check of the ABI he
vignesh
2013/12/16 21:10:57
Done.
| |
165 frame_buffers_ = new vpx_codec_frame_buffer[kVP9MaxFrameBuffers](); | |
fgalligan1
2013/12/16 19:38:43
parenthesis are not needed.
vignesh
2013/12/16 21:10:57
new operator without paranthesis will not zero ini
| |
166 if (vpx_codec_set_frame_buffers(vpx_codec_, | |
167 frame_buffers_, | |
168 kVP9MaxFrameBuffers, | |
169 VpxVideoDecoder::ReallocVP9FrameBuffer, | |
170 NULL)) { | |
171 LOG(ERROR) << "Failed to configure external buffers."; | |
172 return false; | |
173 } | |
174 } | |
175 | |
145 if (config.format() == VideoFrame::YV12A) { | 176 if (config.format() == VideoFrame::YV12A) { |
146 vpx_codec_alpha_ = InitializeVpxContext(vpx_codec_alpha_, config); | 177 vpx_codec_alpha_ = InitializeVpxContext(vpx_codec_alpha_, config); |
147 if (!vpx_codec_alpha_) | 178 if (!vpx_codec_alpha_) |
148 return false; | 179 return false; |
149 } | 180 } |
150 | 181 |
151 return true; | 182 return true; |
152 } | 183 } |
153 | 184 |
154 void VpxVideoDecoder::CloseDecoder() { | 185 void VpxVideoDecoder::CloseDecoder() { |
155 if (vpx_codec_) { | 186 if (vpx_codec_) { |
156 vpx_codec_destroy(vpx_codec_); | 187 vpx_codec_destroy(vpx_codec_); |
157 delete vpx_codec_; | 188 delete vpx_codec_; |
158 vpx_codec_ = NULL; | 189 vpx_codec_ = NULL; |
190 if (frame_buffers_) { | |
191 for (int i = 0; i < kVP9MaxFrameBuffers; i++) | |
192 delete[] frame_buffers_[i].data; | |
193 delete[] frame_buffers_; | |
194 frame_buffers_ = NULL; | |
195 } | |
159 } | 196 } |
160 if (vpx_codec_alpha_) { | 197 if (vpx_codec_alpha_) { |
161 vpx_codec_destroy(vpx_codec_alpha_); | 198 vpx_codec_destroy(vpx_codec_alpha_); |
162 delete vpx_codec_alpha_; | 199 delete vpx_codec_alpha_; |
163 vpx_codec_alpha_ = NULL; | 200 vpx_codec_alpha_ = NULL; |
164 } | 201 } |
165 } | 202 } |
166 | 203 |
167 void VpxVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 204 void VpxVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
168 const DecodeCB& decode_cb) { | 205 const DecodeCB& decode_cb) { |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 | 372 |
336 void VpxVideoDecoder::CopyVpxImageTo(const vpx_image* vpx_image, | 373 void VpxVideoDecoder::CopyVpxImageTo(const vpx_image* vpx_image, |
337 const struct vpx_image* vpx_image_alpha, | 374 const struct vpx_image* vpx_image_alpha, |
338 scoped_refptr<VideoFrame>* video_frame) { | 375 scoped_refptr<VideoFrame>* video_frame) { |
339 CHECK(vpx_image); | 376 CHECK(vpx_image); |
340 CHECK(vpx_image->fmt == VPX_IMG_FMT_I420 || | 377 CHECK(vpx_image->fmt == VPX_IMG_FMT_I420 || |
341 vpx_image->fmt == VPX_IMG_FMT_YV12); | 378 vpx_image->fmt == VPX_IMG_FMT_YV12); |
342 | 379 |
343 gfx::Size size(vpx_image->d_w, vpx_image->d_h); | 380 gfx::Size size(vpx_image->d_w, vpx_image->d_h); |
344 | 381 |
382 if (!vpx_codec_alpha_) { | |
383 *video_frame = VideoFrame::WrapExternalYuvData( | |
384 VideoFrame::YV12, | |
385 size, gfx::Rect(size), config_.natural_size(), | |
386 vpx_image->stride[VPX_PLANE_Y], | |
387 vpx_image->stride[VPX_PLANE_U], | |
388 vpx_image->stride[VPX_PLANE_V], | |
389 vpx_image->planes[VPX_PLANE_Y], | |
390 vpx_image->planes[VPX_PLANE_U], | |
391 vpx_image->planes[VPX_PLANE_V], | |
392 kNoTimestamp(), | |
393 base::Closure()); | |
394 return; | |
395 } | |
396 | |
345 *video_frame = frame_pool_.CreateFrame( | 397 *video_frame = frame_pool_.CreateFrame( |
346 vpx_codec_alpha_ ? VideoFrame::YV12A : VideoFrame::YV12, | 398 vpx_codec_alpha_ ? VideoFrame::YV12A : VideoFrame::YV12, |
347 size, | 399 size, |
348 gfx::Rect(size), | 400 gfx::Rect(size), |
349 config_.natural_size(), | 401 config_.natural_size(), |
350 kNoTimestamp()); | 402 kNoTimestamp()); |
351 | 403 |
352 CopyYPlane(vpx_image->planes[VPX_PLANE_Y], | 404 CopyYPlane(vpx_image->planes[VPX_PLANE_Y], |
353 vpx_image->stride[VPX_PLANE_Y], | 405 vpx_image->stride[VPX_PLANE_Y], |
354 vpx_image->d_h, | 406 vpx_image->d_h, |
355 video_frame->get()); | 407 video_frame->get()); |
356 CopyUPlane(vpx_image->planes[VPX_PLANE_U], | 408 CopyUPlane(vpx_image->planes[VPX_PLANE_U], |
357 vpx_image->stride[VPX_PLANE_U], | 409 vpx_image->stride[VPX_PLANE_U], |
358 (vpx_image->d_h + 1) / 2, | 410 (vpx_image->d_h + 1) / 2, |
359 video_frame->get()); | 411 video_frame->get()); |
360 CopyVPlane(vpx_image->planes[VPX_PLANE_V], | 412 CopyVPlane(vpx_image->planes[VPX_PLANE_V], |
361 vpx_image->stride[VPX_PLANE_V], | 413 vpx_image->stride[VPX_PLANE_V], |
362 (vpx_image->d_h + 1) / 2, | 414 (vpx_image->d_h + 1) / 2, |
363 video_frame->get()); | 415 video_frame->get()); |
364 if (!vpx_codec_alpha_) | |
365 return; | |
366 if (!vpx_image_alpha) { | 416 if (!vpx_image_alpha) { |
367 MakeOpaqueAPlane( | 417 MakeOpaqueAPlane( |
368 vpx_image->stride[VPX_PLANE_Y], vpx_image->d_h, video_frame->get()); | 418 vpx_image->stride[VPX_PLANE_Y], vpx_image->d_h, video_frame->get()); |
369 return; | 419 return; |
370 } | 420 } |
371 CopyAPlane(vpx_image_alpha->planes[VPX_PLANE_Y], | 421 CopyAPlane(vpx_image_alpha->planes[VPX_PLANE_Y], |
372 vpx_image->stride[VPX_PLANE_Y], | 422 vpx_image->stride[VPX_PLANE_Y], |
373 vpx_image->d_h, | 423 vpx_image->d_h, |
374 video_frame->get()); | 424 video_frame->get()); |
375 } | 425 } |
376 | 426 |
377 } // namespace media | 427 } // namespace media |
OLD | NEW |