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

Side by Side Diff: media/filters/vpx_video_decoder.cc

Issue 1561703002: media/vpx: Add support for VP9 alpha channel (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: move alpha decoding to its own function Created 4 years, 11 months 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
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 "media/filters/vpx_video_decoder.h" 5 #include "media/filters/vpx_video_decoder.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 // Generates a "no_longer_needed" closure that holds a reference to this pool. 129 // Generates a "no_longer_needed" closure that holds a reference to this pool.
130 base::Closure CreateFrameCallback(void* fb_priv_data); 130 base::Closure CreateFrameCallback(void* fb_priv_data);
131 131
132 // base::MemoryDumpProvider. 132 // base::MemoryDumpProvider.
133 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, 133 bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
134 base::trace_event::ProcessMemoryDump* pmd) override; 134 base::trace_event::ProcessMemoryDump* pmd) override;
135 135
136 int NumberOfFrameBuffersInUseByDecoder() const; 136 int NumberOfFrameBuffersInUseByDecoder() const;
137 int NumberOfFrameBuffersInUseByDecoderAndVideoFrame() const; 137 int NumberOfFrameBuffersInUseByDecoderAndVideoFrame() const;
138 138
139 private:
140 friend class base::RefCountedThreadSafe<VpxVideoDecoder::MemoryPool>;
141 ~MemoryPool() override;
142
143 // Reference counted frame buffers used for VP9 decoding. Reference counting 139 // Reference counted frame buffers used for VP9 decoding. Reference counting
144 // is done manually because both chromium and libvpx has to release this 140 // is done manually because both chromium and libvpx has to release this
145 // before a buffer can be re-used. 141 // before a buffer can be re-used.
146 struct VP9FrameBuffer { 142 struct VP9FrameBuffer {
147 VP9FrameBuffer() : ref_cnt(0) {} 143 VP9FrameBuffer() : ref_cnt(0) {}
148 std::vector<uint8_t> data; 144 std::vector<uint8_t> data;
145 std::vector<uint8_t> alpha_data;
149 uint32_t ref_cnt; 146 uint32_t ref_cnt;
150 }; 147 };
151 148
149 private:
150 friend class base::RefCountedThreadSafe<VpxVideoDecoder::MemoryPool>;
151 ~MemoryPool() override;
152
152 // Gets the next available frame buffer for use by libvpx. 153 // Gets the next available frame buffer for use by libvpx.
153 VP9FrameBuffer* GetFreeFrameBuffer(size_t min_size); 154 VP9FrameBuffer* GetFreeFrameBuffer(size_t min_size);
154 155
155 // Method that gets called when a VideoFrame that references this pool gets 156 // Method that gets called when a VideoFrame that references this pool gets
156 // destroyed. 157 // destroyed.
157 void OnVideoFrameDestroyed(VP9FrameBuffer* frame_buffer); 158 void OnVideoFrameDestroyed(VP9FrameBuffer* frame_buffer);
158 159
159 // Frame buffers to be used by libvpx for VP9 Decoding. 160 // Frame buffers to be used by libvpx for VP9 Decoding.
160 std::vector<VP9FrameBuffer*> frame_buffers_; 161 std::vector<VP9FrameBuffer*> frame_buffers_;
161 162
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 state_ = kNormal; 374 state_ = kNormal;
374 // PostTask() to avoid calling |closure| inmediately. 375 // PostTask() to avoid calling |closure| inmediately.
375 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure); 376 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, closure);
376 } 377 }
377 378
378 bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) { 379 bool VpxVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config) {
379 if (config.codec() != kCodecVP8 && config.codec() != kCodecVP9) 380 if (config.codec() != kCodecVP8 && config.codec() != kCodecVP9)
380 return false; 381 return false;
381 382
382 // These are the combinations of codec-pixel format supported in principle. 383 // These are the combinations of codec-pixel format supported in principle.
383 // Note that VP9 does not support Alpha in the current implementation.
384 DCHECK( 384 DCHECK(
385 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12) || 385 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12) ||
386 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12A) || 386 (config.codec() == kCodecVP8 && config.format() == PIXEL_FORMAT_YV12A) ||
387 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV12) || 387 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV12) ||
388 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV12A) ||
388 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV24)); 389 (config.codec() == kCodecVP9 && config.format() == PIXEL_FORMAT_YV24));
389 390
390 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS) 391 #if !defined(DISABLE_FFMPEG_VIDEO_DECODERS)
391 // When FFmpegVideoDecoder is available it handles VP8 that doesn't have 392 // When FFmpegVideoDecoder is available it handles VP8 that doesn't have
392 // alpha, and VpxVideoDecoder will handle VP8 with alpha. 393 // alpha, and VpxVideoDecoder will handle VP8 with alpha.
393 if (config.codec() == kCodecVP8 && config.format() != PIXEL_FORMAT_YV12A) 394 if (config.codec() == kCodecVP8 && config.format() != PIXEL_FORMAT_YV12A)
394 return false; 395 return false;
395 #endif 396 #endif
396 397
397 CloseDecoder(); 398 CloseDecoder();
398 399
399 vpx_codec_ = InitializeVpxContext(vpx_codec_, config); 400 vpx_codec_ = InitializeVpxContext(vpx_codec_, config);
400 if (!vpx_codec_) 401 if (!vpx_codec_)
401 return false; 402 return false;
402 403
403 // Configure VP9 to decode on our buffers to skip a data copy on decoding. 404 // Configure VP9 to decode on our buffers to skip a data copy on
405 // decoding. For YV12A-VP9, we use our buffers for the Y, U and V planes and
406 // copy the A plane.
404 if (config.codec() == kCodecVP9) { 407 if (config.codec() == kCodecVP9) {
405 DCHECK_NE(PIXEL_FORMAT_YV12A, config.format());
406 DCHECK(vpx_codec_get_caps(vpx_codec_->iface) & 408 DCHECK(vpx_codec_get_caps(vpx_codec_->iface) &
407 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER); 409 VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER);
408 410
409 memory_pool_ = new MemoryPool(); 411 memory_pool_ = new MemoryPool();
410 if (vpx_codec_set_frame_buffer_functions(vpx_codec_, 412 if (vpx_codec_set_frame_buffer_functions(vpx_codec_,
411 &MemoryPool::GetVP9FrameBuffer, 413 &MemoryPool::GetVP9FrameBuffer,
412 &MemoryPool::ReleaseVP9FrameBuffer, 414 &MemoryPool::ReleaseVP9FrameBuffer,
413 memory_pool_.get())) { 415 memory_pool_.get())) {
414 DLOG(ERROR) << "Failed to configure external buffers. " 416 DLOG(ERROR) << "Failed to configure external buffers. "
415 << vpx_codec_error(vpx_codec_); 417 << vpx_codec_error(vpx_codec_);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 if (!vpx_image) { 465 if (!vpx_image) {
464 *video_frame = nullptr; 466 *video_frame = nullptr;
465 return true; 467 return true;
466 } 468 }
467 469
468 if (vpx_image->user_priv != user_priv) { 470 if (vpx_image->user_priv != user_priv) {
469 DLOG(ERROR) << "Invalid output timestamp."; 471 DLOG(ERROR) << "Invalid output timestamp.";
470 return false; 472 return false;
471 } 473 }
472 474
473 if (!CopyVpxImageToVideoFrame(vpx_image, video_frame)) 475 const vpx_image_t* vpx_image_alpha = nullptr;
476 AlphaDecodeStatus alpha_decode_status =
477 DecodeAlphaPlane(vpx_image, &vpx_image_alpha, buffer);
478 if (alpha_decode_status == kFailure) {
474 return false; 479 return false;
480 } else if (alpha_decode_status == kNoAlphaPlaneData) {
481 *video_frame = nullptr;
482 return true;
483 }
484 if (!CopyVpxImageToVideoFrame(vpx_image, vpx_image_alpha, video_frame)) {
485 return false;
486 }
487 if (vpx_image_alpha && config_.codec() == kCodecVP8) {
488 libyuv::CopyPlane(vpx_image_alpha->planes[VPX_PLANE_Y],
489 vpx_image_alpha->stride[VPX_PLANE_Y],
490 (*video_frame)->visible_data(VideoFrame::kAPlane),
491 (*video_frame)->stride(VideoFrame::kAPlane),
492 (*video_frame)->visible_rect().width(),
493 (*video_frame)->visible_rect().height());
494 }
475 495
476 (*video_frame)->set_timestamp(base::TimeDelta::FromMicroseconds(timestamp)); 496 (*video_frame)->set_timestamp(base::TimeDelta::FromMicroseconds(timestamp));
477 497
478 // Default to the color space from the config, but if the bistream specifies 498 // Default to the color space from the config, but if the bistream specifies
479 // one, prefer that instead. 499 // one, prefer that instead.
480 ColorSpace color_space = config_.color_space(); 500 ColorSpace color_space = config_.color_space();
481 if (vpx_image->cs == VPX_CS_BT_709) 501 if (vpx_image->cs == VPX_CS_BT_709)
482 color_space = COLOR_SPACE_HD_REC709; 502 color_space = COLOR_SPACE_HD_REC709;
483 else if (vpx_image->cs == VPX_CS_BT_601) 503 else if (vpx_image->cs == VPX_CS_BT_601)
484 color_space = COLOR_SPACE_SD_REC601; 504 color_space = COLOR_SPACE_SD_REC601;
485 (*video_frame) 505 (*video_frame)
486 ->metadata() 506 ->metadata()
487 ->SetInteger(VideoFrameMetadata::COLOR_SPACE, color_space); 507 ->SetInteger(VideoFrameMetadata::COLOR_SPACE, color_space);
508 return true;
509 }
488 510
489 if (!vpx_codec_alpha_) 511 AlphaDecodeStatus VpxVideoDecoder::DecodeAlphaPlane(
490 return true; 512 const struct vpx_image* vpx_image,
513 const struct vpx_image** vpx_image_alpha,
DaleCurtis 2016/01/13 01:32:28 possible to avoid passing **?
vignesh 2016/01/13 04:01:10 i can swap this with the return value. that would
DaleCurtis 2016/01/13 18:59:55 It's no different semantically, so what you have i
514 const scoped_refptr<DecoderBuffer>& buffer,
515 scoped_refptr<VideoFrame>* video_frame) {
516 if (vpx_codec_alpha_ && buffer->side_data_size() >= 8) {
DaleCurtis 2016/01/13 01:32:28 return early instead of indenting the whole functi
vignesh 2016/01/15 18:07:13 Done.
517 // First 8 bytes of side data is |side_data_id| in big endian.
518 const uint64_t side_data_id = base::NetToHost64(
519 *(reinterpret_cast<const uint64_t*>(buffer->side_data())));
520 if (side_data_id == 1) {
521 // Try and decode buffer->side_data() minus the first 8 bytes as a full
522 // frame.
523 int64_t timestamp_alpha = buffer->timestamp().InMicroseconds();
524 void* user_priv_alpha = reinterpret_cast<void*>(&timestamp_alpha);
525 {
526 TRACE_EVENT1("video", "vpx_codec_decode_alpha", "timestamp_alpha",
527 timestamp_alpha);
528 vpx_codec_err_t status = vpx_codec_decode(
529 vpx_codec_alpha_, buffer->side_data() + 8,
530 buffer->side_data_size() - 8, user_priv_alpha, 0 /* deadline */);
531 if (status != VPX_CODEC_OK) {
532 DLOG(ERROR) << "vpx_codec_decode() failed for the alpha: "
533 << vpx_codec_error(vpx_codec_);
534 return kError;
535 }
536 }
491 537
492 if (buffer->side_data_size() < 8) { 538 vpx_codec_iter_t iter_alpha = NULL;
493 // TODO(mcasas): Is this a warning or an error? 539 *vpx_image_alpha = vpx_codec_get_frame(vpx_codec_alpha_, &iter_alpha);
494 DLOG(WARNING) << "Making Alpha channel opaque due to missing input"; 540 if (!(*vpx_image_alpha)) {
495 const uint32_t kAlphaOpaqueValue = 255; 541 return kNoAlphaPlaneData;
DaleCurtis 2016/01/13 01:32:28 It's a bit confusing that kOk is returned for non-
vignesh 2016/01/13 04:01:10 I defined the function semantic as follows: * retu
DaleCurtis 2016/01/13 18:59:55 Nope, if nothing sticks out lets just go with this
496 libyuv::SetPlane((*video_frame)->visible_data(VideoFrame::kAPlane), 542 }
497 (*video_frame)->stride(VideoFrame::kAPlane),
498 (*video_frame)->visible_rect().width(),
499 (*video_frame)->visible_rect().height(),
500 kAlphaOpaqueValue);
501 return true;
502 }
503 543
504 // First 8 bytes of side data is |side_data_id| in big endian. 544 if ((*vpx_image_alpha)->user_priv != user_priv_alpha) {
505 const uint64_t side_data_id = base::NetToHost64( 545 DLOG(ERROR) << "Invalid output timestamp on alpha.";
506 *(reinterpret_cast<const uint64_t*>(buffer->side_data()))); 546 return kError;
507 if (side_data_id != 1) 547 }
508 return true;
509 548
510 // Try and decode buffer->side_data() minus the first 8 bytes as a full frame. 549 if ((*vpx_image_alpha)->d_h != vpx_image->d_h ||
511 int64_t timestamp_alpha = buffer->timestamp().InMicroseconds(); 550 (*vpx_image_alpha)->d_w != vpx_image->d_w) {
512 void* user_priv_alpha = reinterpret_cast<void*>(&timestamp_alpha); 551 DLOG(ERROR) << "The alpha plane dimensions are not the same as the "
513 { 552 "image dimensions.";
514 TRACE_EVENT1("video", "vpx_codec_decode_alpha", "timestamp_alpha", 553 return kError;
515 timestamp_alpha); 554 }
516 vpx_codec_err_t status = vpx_codec_decode( 555
517 vpx_codec_alpha_, buffer->side_data() + 8, buffer->side_data_size() - 8, 556 if (config_.codec() == kCodecVP9) {
518 user_priv_alpha, 0 /* deadline */); 557 VpxVideoDecoder::MemoryPool::VP9FrameBuffer* frame_buffer =
519 if (status != VPX_CODEC_OK) { 558 static_cast<VpxVideoDecoder::MemoryPool::VP9FrameBuffer*>(
520 DLOG(ERROR) << "vpx_codec_decode() failed for the alpha: " 559 vpx_image->fb_priv);
521 << vpx_codec_error(vpx_codec_); 560 uint64_t alpha_plane_size =
522 return false; 561 (*vpx_image_alpha)->stride[VPX_PLANE_Y] * (*vpx_image_alpha)->d_h;
562 if (frame_buffer->alpha_data.size() < alpha_plane_size) {
563 frame_buffer->alpha_data.resize(alpha_plane_size);
564 }
565 libyuv::CopyPlane((*vpx_image_alpha)->planes[VPX_PLANE_Y],
566 (*vpx_image_alpha)->stride[VPX_PLANE_Y],
567 &frame_buffer->alpha_data[0],
568 (*vpx_image_alpha)->stride[VPX_PLANE_Y],
569 (*vpx_image_alpha)->d_w, (*vpx_image_alpha)->d_h);
570 }
523 } 571 }
524 } 572 }
525 573 return kOk;
526 vpx_codec_iter_t iter_alpha = NULL;
527 const vpx_image_t* vpx_image_alpha =
528 vpx_codec_get_frame(vpx_codec_alpha_, &iter_alpha);
529 if (!vpx_image_alpha) {
530 *video_frame = nullptr;
531 return true;
532 }
533
534 if (vpx_image_alpha->user_priv != user_priv_alpha) {
535 DLOG(ERROR) << "Invalid output timestamp on alpha.";
536 return false;
537 }
538
539 if (vpx_image_alpha->d_h != vpx_image->d_h ||
540 vpx_image_alpha->d_w != vpx_image->d_w) {
541 DLOG(ERROR) << "The alpha plane dimensions are not the same as the "
542 "image dimensions.";
543 return false;
544 }
545
546 libyuv::CopyPlane(vpx_image_alpha->planes[VPX_PLANE_Y],
547 vpx_image_alpha->stride[VPX_PLANE_Y],
548 (*video_frame)->visible_data(VideoFrame::kAPlane),
549 (*video_frame)->stride(VideoFrame::kAPlane),
550 (*video_frame)->visible_rect().width(),
551 (*video_frame)->visible_rect().height());
552 return true;
553 } 574 }
554 575
555 bool VpxVideoDecoder::CopyVpxImageToVideoFrame( 576 bool VpxVideoDecoder::CopyVpxImageToVideoFrame(
556 const struct vpx_image* vpx_image, 577 const struct vpx_image* vpx_image,
578 const struct vpx_image* vpx_image_alpha,
557 scoped_refptr<VideoFrame>* video_frame) { 579 scoped_refptr<VideoFrame>* video_frame) {
558 DCHECK(vpx_image); 580 DCHECK(vpx_image);
559 581
560 VideoPixelFormat codec_format; 582 VideoPixelFormat codec_format;
561 switch (vpx_image->fmt) { 583 switch (vpx_image->fmt) {
562 case VPX_IMG_FMT_I420: 584 case VPX_IMG_FMT_I420:
563 codec_format = vpx_codec_alpha_ ? PIXEL_FORMAT_YV12A : PIXEL_FORMAT_YV12; 585 codec_format = vpx_image_alpha ? PIXEL_FORMAT_YV12A : PIXEL_FORMAT_YV12;
564 break; 586 break;
565 587
566 case VPX_IMG_FMT_I444: 588 case VPX_IMG_FMT_I444:
567 codec_format = PIXEL_FORMAT_YV24; 589 codec_format = PIXEL_FORMAT_YV24;
568 break; 590 break;
569 591
570 default: 592 default:
571 DLOG(ERROR) << "Unsupported pixel format: " << vpx_image->fmt; 593 DLOG(ERROR) << "Unsupported pixel format: " << vpx_image->fmt;
572 return false; 594 return false;
573 } 595 }
574 596
575 // The mixed |w|/|d_h| in |coded_size| is intentional. Setting the correct 597 // The mixed |w|/|d_h| in |coded_size| is intentional. Setting the correct
576 // coded width is necessary to allow coalesced memory access, which may avoid 598 // coded width is necessary to allow coalesced memory access, which may avoid
577 // frame copies. Setting the correct coded height however does not have any 599 // frame copies. Setting the correct coded height however does not have any
578 // benefit, and only risk copying too much data. 600 // benefit, and only risk copying too much data.
579 const gfx::Size coded_size(vpx_image->w, vpx_image->d_h); 601 const gfx::Size coded_size(vpx_image->w, vpx_image->d_h);
580 const gfx::Size visible_size(vpx_image->d_w, vpx_image->d_h); 602 const gfx::Size visible_size(vpx_image->d_w, vpx_image->d_h);
581 603
582 if (memory_pool_.get()) { 604 if (memory_pool_.get()) {
583 DCHECK_EQ(kCodecVP9, config_.codec()); 605 DCHECK_EQ(kCodecVP9, config_.codec());
584 DCHECK(!vpx_codec_alpha_) << "Uh-oh, VP9 and Alpha shouldn't coexist."; 606 if (vpx_image_alpha) {
585 *video_frame = VideoFrame::WrapExternalYuvData( 607 VpxVideoDecoder::MemoryPool::VP9FrameBuffer* frame_buffer =
586 codec_format, 608 static_cast<VpxVideoDecoder::MemoryPool::VP9FrameBuffer*>(
587 coded_size, gfx::Rect(visible_size), config_.natural_size(), 609 vpx_image->fb_priv);
588 vpx_image->stride[VPX_PLANE_Y], 610 *video_frame = VideoFrame::WrapExternalYuvaData(
589 vpx_image->stride[VPX_PLANE_U], 611 codec_format, coded_size, gfx::Rect(visible_size),
590 vpx_image->stride[VPX_PLANE_V], 612 config_.natural_size(), vpx_image->stride[VPX_PLANE_Y],
591 vpx_image->planes[VPX_PLANE_Y], 613 vpx_image->stride[VPX_PLANE_U], vpx_image->stride[VPX_PLANE_V],
592 vpx_image->planes[VPX_PLANE_U], 614 vpx_image_alpha->stride[VPX_PLANE_Y], vpx_image->planes[VPX_PLANE_Y],
593 vpx_image->planes[VPX_PLANE_V], 615 vpx_image->planes[VPX_PLANE_U], vpx_image->planes[VPX_PLANE_V],
594 kNoTimestamp()); 616 &frame_buffer->alpha_data[0], kNoTimestamp());
617 } else {
618 *video_frame = VideoFrame::WrapExternalYuvData(
619 codec_format, coded_size, gfx::Rect(visible_size),
620 config_.natural_size(), vpx_image->stride[VPX_PLANE_Y],
621 vpx_image->stride[VPX_PLANE_U], vpx_image->stride[VPX_PLANE_V],
622 vpx_image->planes[VPX_PLANE_Y], vpx_image->planes[VPX_PLANE_U],
623 vpx_image->planes[VPX_PLANE_V], kNoTimestamp());
624 }
595 video_frame->get()->AddDestructionObserver( 625 video_frame->get()->AddDestructionObserver(
596 memory_pool_->CreateFrameCallback(vpx_image->fb_priv)); 626 memory_pool_->CreateFrameCallback(vpx_image->fb_priv));
597 627
598 UMA_HISTOGRAM_COUNTS("Media.Vpx.VideoDecoderBuffersInUseByDecoder", 628 UMA_HISTOGRAM_COUNTS("Media.Vpx.VideoDecoderBuffersInUseByDecoder",
599 memory_pool_->NumberOfFrameBuffersInUseByDecoder()); 629 memory_pool_->NumberOfFrameBuffersInUseByDecoder());
600 UMA_HISTOGRAM_COUNTS( 630 UMA_HISTOGRAM_COUNTS(
601 "Media.Vpx.VideoDecoderBuffersInUseByDecoderAndVideoFrame", 631 "Media.Vpx.VideoDecoderBuffersInUseByDecoderAndVideoFrame",
602 memory_pool_->NumberOfFrameBuffersInUseByDecoderAndVideoFrame()); 632 memory_pool_->NumberOfFrameBuffersInUseByDecoderAndVideoFrame());
603 633
604 return true; 634 return true;
(...skipping 15 matching lines...) Expand all
620 (*video_frame)->visible_data(VideoFrame::kUPlane), 650 (*video_frame)->visible_data(VideoFrame::kUPlane),
621 (*video_frame)->stride(VideoFrame::kUPlane), 651 (*video_frame)->stride(VideoFrame::kUPlane),
622 (*video_frame)->visible_data(VideoFrame::kVPlane), 652 (*video_frame)->visible_data(VideoFrame::kVPlane),
623 (*video_frame)->stride(VideoFrame::kVPlane), coded_size.width(), 653 (*video_frame)->stride(VideoFrame::kVPlane), coded_size.width(),
624 coded_size.height()); 654 coded_size.height());
625 655
626 return true; 656 return true;
627 } 657 }
628 658
629 } // namespace media 659 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698