Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.cc

Issue 11316045: Add a libvpx video decoder to ClearKeyCdm and move the fake video decoder to its own class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h ('k') | webkit/media/webkit_media.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h" 5 #include "webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "media/base/buffers.h" 9 #include "media/base/buffers.h"
10 #include "media/base/limits.h" 10 #include "media/base/limits.h"
11 #include "webkit/media/crypto/ppapi/content_decryption_module.h" 11 #include "webkit/media/crypto/ppapi/content_decryption_module.h"
12 12
13 // Include FFmpeg header files. 13 // Include FFmpeg header files.
14 extern "C" { 14 extern "C" {
15 // Temporarily disable possible loss of data warning. 15 // Temporarily disable possible loss of data warning.
16 MSVC_PUSH_DISABLE_WARNING(4244); 16 MSVC_PUSH_DISABLE_WARNING(4244);
17 #include <libavcodec/avcodec.h> 17 #include <libavcodec/avcodec.h>
18 MSVC_POP_WARNING(); 18 MSVC_POP_WARNING();
19 } // extern "C" 19 } // extern "C"
20 20
21 // TODO(tomfinegan): Move libvpx decode support somewhere else. Another ifdef
22 // is a crime against humanity etc etc...
23 #define USE_LIBVPX 1
24
25 #if defined (USE_LIBVPX)
26 // Include libvpx header files.
27 extern "C" {
28 #define VPX_CODEC_DISABLE_COMPAT 1
29 #include "third_party/libvpx/libvpx.h"
30 }
31 #endif
32
33 // TODO(tomfinegan): I'm seeing bad video output, so I put in code w/memcpy's
34 // instead of using |CopyPlane()| to try to figure out what was going on. Turns
35 // out video output is bad with or without libvpx in the mix. I've left this
36 // mess here because full plane copies are what the stuff we're comparing
37 // against does, so maybe it's of some use...
xhwang 2012/11/16 17:33:02 Is this what you are seeing? http://code.google.co
Tom Finegan 2012/11/16 19:36:51 Yeah, that's the problem. Things look fine with --
38 // #define USE_COPYPLANE_WITH_LIBVPX 1
39
21 namespace webkit_media { 40 namespace webkit_media {
22 41
23 static const int kDecodeThreads = 1; 42 static const int kDecodeThreads = 1;
24 43
25 static cdm::VideoFormat PixelFormatToCdmVideoFormat(PixelFormat pixel_format) { 44 static cdm::VideoFormat PixelFormatToCdmVideoFormat(PixelFormat pixel_format) {
26 switch (pixel_format) { 45 switch (pixel_format) {
27 case PIX_FMT_YUV420P: 46 case PIX_FMT_YUV420P:
28 return cdm::kYv12; 47 return cdm::kYv12;
29 default: 48 default:
30 DVLOG(1) << "Unsupported PixelFormat: " << pixel_format; 49 DVLOG(1) << "Unsupported PixelFormat: " << pixel_format;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 memcpy(target + target_offset, 145 memcpy(target + target_offset,
127 source + source_offset, 146 source + source_offset,
128 copy_bytes_per_row); 147 copy_bytes_per_row);
129 } 148 }
130 } 149 }
131 150
132 FFmpegCdmVideoDecoder::FFmpegCdmVideoDecoder(cdm::Allocator* allocator) 151 FFmpegCdmVideoDecoder::FFmpegCdmVideoDecoder(cdm::Allocator* allocator)
133 : codec_context_(NULL), 152 : codec_context_(NULL),
134 av_frame_(NULL), 153 av_frame_(NULL),
135 is_initialized_(false), 154 is_initialized_(false),
136 allocator_(allocator) { 155 allocator_(allocator),
156 vpx_codec_(NULL),
157 vpx_image_(NULL) {
137 } 158 }
138 159
139 FFmpegCdmVideoDecoder::~FFmpegCdmVideoDecoder() { 160 FFmpegCdmVideoDecoder::~FFmpegCdmVideoDecoder() {
140 ReleaseFFmpegResources(); 161 ReleaseFFmpegResources();
141 } 162 }
142 163
143 bool FFmpegCdmVideoDecoder::Initialize(const cdm::VideoDecoderConfig& config) { 164 bool FFmpegCdmVideoDecoder::Initialize(const cdm::VideoDecoderConfig& config) {
144 DVLOG(1) << "Initialize()"; 165 DVLOG(1) << "Initialize()";
145 166
146 if (!IsValidOutputConfig(config.format, config.coded_size)) { 167 if (!IsValidOutputConfig(config.format, config.coded_size)) {
147 LOG(ERROR) << "Initialize(): invalid video decoder configuration."; 168 LOG(ERROR) << "Initialize(): invalid video decoder configuration.";
148 return false; 169 return false;
149 } 170 }
150 171
151 if (is_initialized_) { 172 if (is_initialized_) {
152 LOG(ERROR) << "Initialize(): Already initialized."; 173 LOG(ERROR) << "Initialize(): Already initialized.";
153 return false; 174 return false;
154 } 175 }
155 176
156 // Initialize AVCodecContext structure. 177 // TODO(tomfinegan): Move libvpx decode support somewhere else.
157 codec_context_ = avcodec_alloc_context3(NULL); 178 #if defined(USE_LIBVPX)
158 CdmVideoDecoderConfigToAVCodecContext(config, codec_context_); 179 if (config.codec == cdm::VideoDecoderConfig::kCodecVp8) {
180 return InitializeLibvpx(config);
181 }
182 #endif
159 183
160 // Enable motion vector search (potentially slow), strong deblocking filter 184 return InitializeFFmpeg(config);
161 // for damaged macroblocks, and set our error detection sensitivity.
162 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
163 codec_context_->err_recognition = AV_EF_CAREFUL;
164 codec_context_->thread_count = kDecodeThreads;
165 codec_context_->opaque = this;
166 codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
167
168 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
169 if (!codec) {
170 LOG(ERROR) << "Initialize(): avcodec_find_decoder failed.";
171 return false;
172 }
173
174 int status;
175 if ((status = avcodec_open2(codec_context_, codec, NULL)) < 0) {
176 LOG(ERROR) << "Initialize(): avcodec_open2 failed: " << status;
177 return false;
178 }
179
180 av_frame_ = avcodec_alloc_frame();
181 is_initialized_ = true;
182
183 return true;
184 } 185 }
185 186
186 void FFmpegCdmVideoDecoder::Deinitialize() { 187 void FFmpegCdmVideoDecoder::Deinitialize() {
187 DVLOG(1) << "Deinitialize()"; 188 DVLOG(1) << "Deinitialize()";
188 ReleaseFFmpegResources(); 189 ReleaseFFmpegResources();
190
191 if (vpx_codec_) {
192 vpx_codec_destroy(vpx_codec_);
193 vpx_codec_ = NULL;
194 }
195
189 is_initialized_ = false; 196 is_initialized_ = false;
190 } 197 }
191 198
192 void FFmpegCdmVideoDecoder::Reset() { 199 void FFmpegCdmVideoDecoder::Reset() {
193 DVLOG(1) << "Reset()"; 200 DVLOG(1) << "Reset()";
194 avcodec_flush_buffers(codec_context_); 201
202 if (codec_context_)
203 avcodec_flush_buffers(codec_context_);
195 } 204 }
196 205
197 // static 206 // static
198 bool FFmpegCdmVideoDecoder::IsValidOutputConfig(cdm::VideoFormat format, 207 bool FFmpegCdmVideoDecoder::IsValidOutputConfig(cdm::VideoFormat format,
199 const cdm::Size& data_size) { 208 const cdm::Size& data_size) {
200 return ((format == cdm::kYv12 || format == cdm::kI420) && 209 return ((format == cdm::kYv12 || format == cdm::kI420) &&
201 (data_size.width % 2) == 0 && (data_size.height % 2) == 0 && 210 (data_size.width % 2) == 0 && (data_size.height % 2) == 0 &&
202 data_size.width > 0 && data_size.height > 0 && 211 data_size.width > 0 && data_size.height > 0 &&
203 data_size.width <= media::limits::kMaxDimension && 212 data_size.width <= media::limits::kMaxDimension &&
204 data_size.height <= media::limits::kMaxDimension && 213 data_size.height <= media::limits::kMaxDimension &&
205 data_size.width * data_size.height <= media::limits::kMaxCanvas); 214 data_size.width * data_size.height <= media::limits::kMaxCanvas);
206 } 215 }
207 216
208 cdm::Status FFmpegCdmVideoDecoder::DecodeFrame( 217 cdm::Status FFmpegCdmVideoDecoder::DecodeFrame(
209 const uint8_t* compressed_frame, 218 const uint8_t* compressed_frame,
210 int32_t compressed_frame_size, 219 int32_t compressed_frame_size,
211 int64_t timestamp, 220 int64_t timestamp,
212 cdm::VideoFrame* decoded_frame) { 221 cdm::VideoFrame* decoded_frame) {
213 DVLOG(1) << "DecodeFrame()";
214 DCHECK(decoded_frame); 222 DCHECK(decoded_frame);
215 223
216 // Create a packet for input data. 224 // TODO(tomfinegan): Move libvpx decode support somewhere else.
217 AVPacket packet; 225 #if defined(USE_LIBVPX)
218 av_init_packet(&packet); 226 if (vpx_codec_) {
227 return DecodeFrameLibvpx(compressed_frame, compressed_frame_size,
228 timestamp,
229 decoded_frame);
230 }
231 #endif
219 232
220 // The FFmpeg API does not allow us to have const read-only pointers. 233 return DecodeFrameFFmpeg(compressed_frame, compressed_frame_size, timestamp,
221 packet.data = const_cast<uint8_t*>(compressed_frame); 234 decoded_frame);
222 packet.size = compressed_frame_size;
223
224 // Let FFmpeg handle presentation timestamp reordering.
225 codec_context_->reordered_opaque = timestamp;
226
227 // Reset frame to default values.
228 avcodec_get_frame_defaults(av_frame_);
229
230 // This is for codecs not using get_buffer to initialize
231 // |av_frame_->reordered_opaque|
232 av_frame_->reordered_opaque = codec_context_->reordered_opaque;
233
234 int frame_decoded = 0;
235 int result = avcodec_decode_video2(codec_context_,
236 av_frame_,
237 &frame_decoded,
238 &packet);
239 // Log the problem when we can't decode a video frame and exit early.
240 if (result < 0) {
241 LOG(ERROR) << "DecodeFrame(): Error decoding video frame with timestamp: "
242 << timestamp << " us, packet size: " << packet.size << " bytes";
243 return cdm::kDecodeError;
244 }
245
246 // If no frame was produced then signal that more data is required to produce
247 // more frames.
248 if (frame_decoded == 0)
249 return cdm::kNeedMoreData;
250
251 // The decoder is in a bad state and not decoding correctly.
252 // Checking for NULL avoids a crash.
253 if (!av_frame_->data[cdm::VideoFrame::kYPlane] ||
254 !av_frame_->data[cdm::VideoFrame::kUPlane] ||
255 !av_frame_->data[cdm::VideoFrame::kVPlane]) {
256 LOG(ERROR) << "DecodeFrame(): Video frame has invalid frame data.";
257 return cdm::kDecodeError;
258 }
259
260 if (!CopyAvFrameTo(decoded_frame)) {
261 LOG(ERROR) << "DecodeFrame() could not copy video frame to output buffer.";
262 return cdm::kDecodeError;
263 }
264
265 return cdm::kSuccess;
266 } 235 }
267 236
268 bool FFmpegCdmVideoDecoder::CopyAvFrameTo(cdm::VideoFrame* cdm_video_frame) { 237 bool FFmpegCdmVideoDecoder::CopyAvFrameTo(cdm::VideoFrame* cdm_video_frame) {
269 DCHECK(cdm_video_frame); 238 DCHECK(cdm_video_frame);
270 DCHECK_EQ(av_frame_->format, PIX_FMT_YUV420P); 239 DCHECK_EQ(av_frame_->format, PIX_FMT_YUV420P);
271 DCHECK_EQ(av_frame_->width % 2, 0); 240 DCHECK_EQ(av_frame_->width % 2, 0);
272 DCHECK_EQ(av_frame_->height % 2, 0); 241 DCHECK_EQ(av_frame_->height % 2, 0);
273 242
274 const int y_size = av_frame_->width * av_frame_->height; 243 const int y_size = av_frame_->width * av_frame_->height;
275 const int uv_size = y_size / 2; 244 const int uv_size = y_size / 2;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 289
321 cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane, av_frame_->width); 290 cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane, av_frame_->width);
322 cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane, uv_stride); 291 cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane, uv_stride);
323 cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane, uv_stride); 292 cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane, uv_stride);
324 293
325 cdm_video_frame->set_timestamp(av_frame_->reordered_opaque); 294 cdm_video_frame->set_timestamp(av_frame_->reordered_opaque);
326 295
327 return true; 296 return true;
328 } 297 }
329 298
299 bool FFmpegCdmVideoDecoder::CopyVpxImageTo(cdm::VideoFrame* cdm_video_frame) {
300 DCHECK(cdm_video_frame);
301 DCHECK_EQ(vpx_image_->fmt, VPX_IMG_FMT_I420);
302 DCHECK_EQ(vpx_image_->d_w % 2, 0U);
303 DCHECK_EQ(vpx_image_->d_h % 2, 0U);
304
305 #if defined(USE_COPYPLANE_WITH_LIBVPX)
306 const int y_size = vpx_image_->d_w * vpx_image_->d_h;
307 const int uv_size = y_size / 2;
308 const int space_required = y_size + (uv_size * 2);
309
310 DCHECK(!cdm_video_frame->frame_buffer());
311 cdm_video_frame->set_frame_buffer(allocator_->Allocate(space_required));
312 if (!cdm_video_frame->frame_buffer()) {
313 LOG(ERROR) << "CopyVpxImageTo() cdm::Allocator::Allocate failed.";
314 return false;
315 }
316
317 CopyPlane(vpx_image_->planes[VPX_PLANE_Y],
318 vpx_image_->stride[VPX_PLANE_Y],
319 vpx_image_->d_w,
320 vpx_image_->d_h,
321 vpx_image_->d_w,
322 cdm_video_frame->frame_buffer()->data());
323
324 const int uv_stride = vpx_image_->d_w / 2;
325 const int uv_rows = vpx_image_->d_h / 2;
326 CopyPlane(vpx_image_->planes[VPX_PLANE_U],
327 vpx_image_->stride[VPX_PLANE_U],
328 uv_stride,
329 uv_rows,
330 uv_stride,
331 cdm_video_frame->frame_buffer()->data() + y_size);
332
333 CopyPlane(vpx_image_->planes[VPX_PLANE_V],
334 vpx_image_->stride[VPX_PLANE_V],
335 uv_stride,
336 uv_rows,
337 uv_stride,
338 cdm_video_frame->frame_buffer()->data() + y_size + uv_size);
339
340 cdm_video_frame->set_format(cdm::kYv12);
341
342 cdm::Size video_frame_size;
343 video_frame_size.width = vpx_image_->d_w;
344 video_frame_size.height = vpx_image_->d_h;
345 cdm_video_frame->set_size(video_frame_size);
346
347 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, 0);
348 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, y_size);
349 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kVPlane,
350 y_size + uv_size);
351
352 cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane, vpx_image_->d_w);
353 cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane, uv_stride);
354 cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane, uv_stride);
355 #else
356 const int y_size = vpx_image_->stride[VPX_PLANE_Y] * vpx_image_->d_h;
357 const int uv_rows = vpx_image_->d_h / 2;
358 const int u_size = vpx_image_->stride[VPX_PLANE_U] * uv_rows;
359 const int v_size = vpx_image_->stride[VPX_PLANE_V] * uv_rows;
360 const int space_required = y_size + u_size + v_size;
361
362 DCHECK(!cdm_video_frame->frame_buffer());
363 cdm_video_frame->set_frame_buffer(allocator_->Allocate(space_required));
364 if (!cdm_video_frame->frame_buffer()) {
365 LOG(ERROR) << "CopyVpxImageTo() cdm::Allocator::Allocate failed.";
366 return false;
367 }
368
369 memcpy(cdm_video_frame->frame_buffer()->data(),
370 vpx_image_->planes[VPX_PLANE_Y],
371 y_size);
372 memcpy(cdm_video_frame->frame_buffer()->data() + y_size,
373 vpx_image_->planes[VPX_PLANE_U],
374 u_size);
375 memcpy(cdm_video_frame->frame_buffer()->data() + y_size + u_size,
376 vpx_image_->planes[VPX_PLANE_V],
377 v_size);
378
379 cdm_video_frame->set_format(cdm::kYv12);
380
381 cdm::Size video_frame_size;
382 video_frame_size.width = vpx_image_->d_w;
383 video_frame_size.height = vpx_image_->d_h;
384 cdm_video_frame->set_size(video_frame_size);
385
386 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kYPlane, 0);
387 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kUPlane, y_size);
388 cdm_video_frame->set_plane_offset(cdm::VideoFrame::kVPlane,
389 y_size + u_size);
390
391 cdm_video_frame->set_stride(cdm::VideoFrame::kYPlane,
392 vpx_image_->stride[VPX_PLANE_Y]);
393 cdm_video_frame->set_stride(cdm::VideoFrame::kUPlane,
394 vpx_image_->stride[VPX_PLANE_U]);
395 cdm_video_frame->set_stride(cdm::VideoFrame::kVPlane,
396 vpx_image_->stride[VPX_PLANE_V]);
397 #endif // USE_COPYPLANE_WITH_LIBVPX
398
399 return true;
400 }
401
330 void FFmpegCdmVideoDecoder::ReleaseFFmpegResources() { 402 void FFmpegCdmVideoDecoder::ReleaseFFmpegResources() {
331 DVLOG(1) << "ReleaseFFmpegResources()"; 403 DVLOG(1) << "ReleaseFFmpegResources()";
332 404
333 if (codec_context_) { 405 if (codec_context_) {
334 av_free(codec_context_->extradata); 406 av_free(codec_context_->extradata);
335 avcodec_close(codec_context_); 407 avcodec_close(codec_context_);
336 av_free(codec_context_); 408 av_free(codec_context_);
337 codec_context_ = NULL; 409 codec_context_ = NULL;
338 } 410 }
339 if (av_frame_) { 411 if (av_frame_) {
340 av_free(av_frame_); 412 av_free(av_frame_);
341 av_frame_ = NULL; 413 av_frame_ = NULL;
342 } 414 }
343 } 415 }
344 416
417 bool FFmpegCdmVideoDecoder::InitializeFFmpeg(
418 const cdm::VideoDecoderConfig& config) {
419 // Initialize AVCodecContext structure.
420 codec_context_ = avcodec_alloc_context3(NULL);
421 CdmVideoDecoderConfigToAVCodecContext(config, codec_context_);
422
423 // Enable motion vector search (potentially slow), strong deblocking filter
424 // for damaged macroblocks, and set our error detection sensitivity.
425 codec_context_->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
426 codec_context_->err_recognition = AV_EF_CAREFUL;
427 codec_context_->thread_count = kDecodeThreads;
428 codec_context_->opaque = this;
429 codec_context_->flags |= CODEC_FLAG_EMU_EDGE;
430
431 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
432 if (!codec) {
433 LOG(ERROR) << "InitializeFFmpeg(): avcodec_find_decoder failed.";
434 return false;
435 }
436
437 int status;
438 if ((status = avcodec_open2(codec_context_, codec, NULL)) < 0) {
439 LOG(ERROR) << "InitializeFFmpeg(): avcodec_open2 failed: " << status;
440 return false;
441 }
442
443 av_frame_ = avcodec_alloc_frame();
444 is_initialized_ = true;
445
446 return true;
447 }
448
449 bool FFmpegCdmVideoDecoder::InitializeLibvpx(
450 const cdm::VideoDecoderConfig& config) {
451 vpx_codec_ = new vpx_codec_ctx_t();
452 vpx_codec_dec_cfg_t vpx_config = {0};
453 vpx_config.w = config.coded_size.width;
454 vpx_config.h = config.coded_size.height;
455 vpx_config.threads = kDecodeThreads;
456
457 vpx_codec_err_t status = vpx_codec_dec_init(vpx_codec_,
458 vpx_codec_vp8_dx(),
459 &vpx_config,
460 0);
461 if (status != VPX_CODEC_OK) {
462 LOG(ERROR) << "InitializeLibvpx(): vpx_codec_dec_init failed, ret="
463 << status;
464 delete vpx_codec_;
465 vpx_codec_ = NULL;
466 }
467
468 is_initialized_ = true;
469 return true;
470 }
471
472 cdm::Status FFmpegCdmVideoDecoder::DecodeFrameFFmpeg(
473 const uint8_t* compressed_frame,
474 int32_t compressed_frame_size,
475 int64_t timestamp,
476 cdm::VideoFrame* decoded_frame) {
477 DVLOG(1) << "DecodeFrameFFmpeg()";
478
479 // Create a packet for input data.
480 AVPacket packet;
481 av_init_packet(&packet);
482
483 // The FFmpeg API does not allow us to have const read-only pointers.
484 packet.data = const_cast<uint8_t*>(compressed_frame);
485 packet.size = compressed_frame_size;
486
487 // Let FFmpeg handle presentation timestamp reordering.
488 codec_context_->reordered_opaque = timestamp;
489
490 // Reset frame to default values.
491 avcodec_get_frame_defaults(av_frame_);
492
493 // This is for codecs not using get_buffer to initialize
494 // |av_frame_->reordered_opaque|
495 av_frame_->reordered_opaque = codec_context_->reordered_opaque;
496
497 int frame_decoded = 0;
498 int result = avcodec_decode_video2(codec_context_,
499 av_frame_,
500 &frame_decoded,
501 &packet);
502 // Log the problem when we can't decode a video frame and exit early.
503 if (result < 0) {
504 LOG(ERROR) << "DecodeFrameFFmpeg(): Error decoding video frame with "
505 << "timestamp: " << timestamp << " us, packet size: "
506 << packet.size << " bytes";
507 return cdm::kDecodeError;
508 }
509
510 // If no frame was produced then signal that more data is required to produce
511 // more frames.
512 if (frame_decoded == 0)
513 return cdm::kNeedMoreData;
514
515 // The decoder is in a bad state and not decoding correctly.
516 // Checking for NULL avoids a crash.
517 if (!av_frame_->data[cdm::VideoFrame::kYPlane] ||
518 !av_frame_->data[cdm::VideoFrame::kUPlane] ||
519 !av_frame_->data[cdm::VideoFrame::kVPlane]) {
520 LOG(ERROR) << "DecodeFrameFFmpeg(): Video frame has invalid frame data.";
521 return cdm::kDecodeError;
522 }
523
524 if (!CopyAvFrameTo(decoded_frame)) {
525 LOG(ERROR) << "DecodeFrameFFmpeg() could not copy video frame to output "
526 << "buffer.";
527 return cdm::kDecodeError;
528 }
529
530 return cdm::kSuccess;
531 }
532
533 cdm::Status FFmpegCdmVideoDecoder::DecodeFrameLibvpx(
534 const uint8_t* compressed_frame,
535 int32_t compressed_frame_size,
536 int64_t timestamp,
537 cdm::VideoFrame* decoded_frame) {
538 DVLOG(1) << "DecodeFrameLibvpx()";
539
540 // Pass |compressed_frame| to libvpx.
541 void* user_priv = reinterpret_cast<void*>(&timestamp);
542 vpx_codec_err_t status = vpx_codec_decode(vpx_codec_,
543 compressed_frame,
544 compressed_frame_size,
545 user_priv,
546 0);
547 if (status != VPX_CODEC_OK) {
548 LOG(ERROR) << "DecodeFrameLibvpx(): vpx_codec_decode failed, status="
549 << status;
550 return cdm::kDecodeError;
551 }
552
553 // Gets pointer to decoded data.
554 vpx_codec_iter_t iter = NULL;
555 vpx_image_ = vpx_codec_get_frame(vpx_codec_, &iter);
556 if (!vpx_image_)
557 return cdm::kNeedMoreData;
558
559 if (vpx_image_->user_priv != reinterpret_cast<void*>(&timestamp)) {
560 LOG(ERROR) << "DecodeFrameLibvpx() invalid output timestamp.";
561 return cdm::kDecodeError;
562 }
563 decoded_frame->set_timestamp(timestamp);
564
565 if (!CopyVpxImageTo(decoded_frame)) {
566 LOG(ERROR) << "DecodeFrameLibvpx() could not copy vpx image to output "
567 << "buffer.";
568 return cdm::kDecodeError;
569 }
570
Tom Finegan 2012/11/16 10:29:54 Oops... I'll fix this whitespace.
571
572
573
574
575 return cdm::kSuccess;
576 }
577
345 } // namespace webkit_media 578 } // namespace webkit_media
OLDNEW
« no previous file with comments | « webkit/media/crypto/ppapi/ffmpeg_cdm_video_decoder.h ('k') | webkit/media/webkit_media.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698