LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/api/video - i420_buffer.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 116 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 29 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : #include "webrtc/api/video/i420_buffer.h"
      11             : 
      12             : #include <string.h>
      13             : 
      14             : #include <algorithm>
      15             : #include <utility>
      16             : 
      17             : #include "webrtc/base/checks.h"
      18             : #include "webrtc/base/keep_ref_until_done.h"
      19             : #include "libyuv/convert.h"
      20             : #include "libyuv/planar_functions.h"
      21             : #include "libyuv/scale.h"
      22             : 
      23             : // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
      24             : static const int kBufferAlignment = 64;
      25             : 
      26             : namespace webrtc {
      27             : 
      28             : namespace {
      29             : 
      30           0 : int I420DataSize(int height, int stride_y, int stride_u, int stride_v) {
      31           0 :   return stride_y * height + (stride_u + stride_v) * ((height + 1) / 2);
      32             : }
      33             : 
      34             : }  // namespace
      35             : 
      36           0 : I420Buffer::I420Buffer(int width, int height)
      37           0 :     : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) {
      38           0 : }
      39             : 
      40           0 : I420Buffer::I420Buffer(int width,
      41             :                        int height,
      42             :                        int stride_y,
      43             :                        int stride_u,
      44           0 :                        int stride_v)
      45             :     : width_(width),
      46             :       height_(height),
      47             :       stride_y_(stride_y),
      48             :       stride_u_(stride_u),
      49             :       stride_v_(stride_v),
      50           0 :       data_(static_cast<uint8_t*>(AlignedMalloc(
      51           0 :           I420DataSize(height, stride_y, stride_u, stride_v),
      52           0 :           kBufferAlignment))) {
      53           0 :   RTC_DCHECK_GT(width, 0);
      54           0 :   RTC_DCHECK_GT(height, 0);
      55           0 :   RTC_DCHECK_GE(stride_y, width);
      56           0 :   RTC_DCHECK_GE(stride_u, (width + 1) / 2);
      57           0 :   RTC_DCHECK_GE(stride_v, (width + 1) / 2);
      58           0 : }
      59             : 
      60           0 : I420Buffer::~I420Buffer() {
      61           0 : }
      62             : 
      63             : // static
      64           0 : rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width, int height) {
      65           0 :   return new rtc::RefCountedObject<I420Buffer>(width, height);
      66             : }
      67             : 
      68             : // static
      69           0 : rtc::scoped_refptr<I420Buffer> I420Buffer::Create(int width,
      70             :                                                   int height,
      71             :                                                   int stride_y,
      72             :                                                   int stride_u,
      73             :                                                   int stride_v) {
      74             :   return new rtc::RefCountedObject<I420Buffer>(
      75           0 :       width, height, stride_y, stride_u, stride_v);
      76             : }
      77             : 
      78             : // static
      79           0 : rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
      80             :     const VideoFrameBuffer& source) {
      81           0 :   return Copy(source.width(), source.height(),
      82           0 :               source.DataY(), source.StrideY(),
      83           0 :               source.DataU(), source.StrideU(),
      84           0 :               source.DataV(), source.StrideV());
      85             : }
      86             : 
      87             : // static
      88           0 : rtc::scoped_refptr<I420Buffer> I420Buffer::Copy(
      89             :       int width, int height,
      90             :       const uint8_t* data_y, int stride_y,
      91             :       const uint8_t* data_u, int stride_u,
      92             :       const uint8_t* data_v, int stride_v) {
      93             :   // Note: May use different strides than the input data.
      94           0 :   rtc::scoped_refptr<I420Buffer> buffer = Create(width, height);
      95           0 :   RTC_CHECK_EQ(0, libyuv::I420Copy(data_y, stride_y,
      96             :                                    data_u, stride_u,
      97             :                                    data_v, stride_v,
      98             :                                    buffer->MutableDataY(), buffer->StrideY(),
      99             :                                    buffer->MutableDataU(), buffer->StrideU(),
     100             :                                    buffer->MutableDataV(), buffer->StrideV(),
     101           0 :                                    width, height));
     102           0 :   return buffer;
     103             : }
     104             : 
     105             : // static
     106           0 : rtc::scoped_refptr<I420Buffer> I420Buffer::Rotate(
     107             :     const VideoFrameBuffer& src, VideoRotation rotation) {
     108           0 :   RTC_CHECK(src.DataY());
     109           0 :   RTC_CHECK(src.DataU());
     110           0 :   RTC_CHECK(src.DataV());
     111             : 
     112           0 :   int rotated_width = src.width();
     113           0 :   int rotated_height = src.height();
     114           0 :   if (rotation == webrtc::kVideoRotation_90 ||
     115             :       rotation == webrtc::kVideoRotation_270) {
     116           0 :     std::swap(rotated_width, rotated_height);
     117             :   }
     118             : 
     119             :   rtc::scoped_refptr<webrtc::I420Buffer> buffer =
     120           0 :       I420Buffer::Create(rotated_width, rotated_height);
     121             : 
     122           0 :   RTC_CHECK_EQ(0, libyuv::I420Rotate(
     123             :       src.DataY(), src.StrideY(),
     124             :       src.DataU(), src.StrideU(),
     125             :       src.DataV(), src.StrideV(),
     126             :       buffer->MutableDataY(), buffer->StrideY(), buffer->MutableDataU(),
     127             :       buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(),
     128             :       src.width(), src.height(),
     129           0 :       static_cast<libyuv::RotationMode>(rotation)));
     130             : 
     131           0 :   return buffer;
     132             : }
     133             : 
     134             : // static
     135           0 : rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::Rotate(
     136             :     rtc::scoped_refptr<VideoFrameBuffer> src,
     137             :     VideoRotation rotation) {
     138           0 :   if (rotation == webrtc::kVideoRotation_0) {
     139           0 :     return src;
     140             :   } else {
     141           0 :     return Rotate(*src, rotation);
     142             :   }
     143             : }
     144             : 
     145           0 : void I420Buffer::InitializeData() {
     146           0 :   memset(data_.get(), 0,
     147           0 :          I420DataSize(height_, stride_y_, stride_u_, stride_v_));
     148           0 : }
     149             : 
     150           0 : int I420Buffer::width() const {
     151           0 :   return width_;
     152             : }
     153             : 
     154           0 : int I420Buffer::height() const {
     155           0 :   return height_;
     156             : }
     157             : 
     158           0 : const uint8_t* I420Buffer::DataY() const {
     159           0 :   return data_.get();
     160             : }
     161           0 : const uint8_t* I420Buffer::DataU() const {
     162           0 :   return data_.get() + stride_y_ * height_;
     163             : }
     164           0 : const uint8_t* I420Buffer::DataV() const {
     165           0 :   return data_.get() + stride_y_ * height_ + stride_u_ * ((height_ + 1) / 2);
     166             : }
     167             : 
     168           0 : int I420Buffer::StrideY() const {
     169           0 :   return stride_y_;
     170             : }
     171           0 : int I420Buffer::StrideU() const {
     172           0 :   return stride_u_;
     173             : }
     174           0 : int I420Buffer::StrideV() const {
     175           0 :   return stride_v_;
     176             : }
     177             : 
     178           0 : void* I420Buffer::native_handle() const {
     179           0 :   return nullptr;
     180             : }
     181             : 
     182           0 : rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::NativeToI420Buffer() {
     183           0 :   RTC_NOTREACHED();
     184           0 :   return nullptr;
     185             : }
     186             : 
     187           0 : uint8_t* I420Buffer::MutableDataY() {
     188           0 :   return const_cast<uint8_t*>(DataY());
     189             : }
     190           0 : uint8_t* I420Buffer::MutableDataU() {
     191           0 :   return const_cast<uint8_t*>(DataU());
     192             : }
     193           0 : uint8_t* I420Buffer::MutableDataV() {
     194           0 :   return const_cast<uint8_t*>(DataV());
     195             : }
     196             : 
     197             : // static
     198           0 : void I420Buffer::SetBlack(I420Buffer* buffer) {
     199           0 :   RTC_CHECK(libyuv::I420Rect(buffer->MutableDataY(), buffer->StrideY(),
     200             :                              buffer->MutableDataU(), buffer->StrideU(),
     201             :                              buffer->MutableDataV(), buffer->StrideV(),
     202             :                              0, 0, buffer->width(), buffer->height(),
     203           0 :                              0, 128, 128) == 0);
     204           0 : }
     205             : 
     206           0 : void I420Buffer::CropAndScaleFrom(
     207             :     const VideoFrameBuffer& src,
     208             :     int offset_x,
     209             :     int offset_y,
     210             :     int crop_width,
     211             :     int crop_height) {
     212           0 :   RTC_CHECK_LE(crop_width, src.width());
     213           0 :   RTC_CHECK_LE(crop_height, src.height());
     214           0 :   RTC_CHECK_LE(crop_width + offset_x, src.width());
     215           0 :   RTC_CHECK_LE(crop_height + offset_y, src.height());
     216           0 :   RTC_CHECK_GE(offset_x, 0);
     217           0 :   RTC_CHECK_GE(offset_y, 0);
     218             : 
     219             :   // Make sure offset is even so that u/v plane becomes aligned.
     220           0 :   const int uv_offset_x = offset_x / 2;
     221           0 :   const int uv_offset_y = offset_y / 2;
     222           0 :   offset_x = uv_offset_x * 2;
     223           0 :   offset_y = uv_offset_y * 2;
     224             : 
     225             :   const uint8_t* y_plane =
     226           0 :       src.DataY() + src.StrideY() * offset_y + offset_x;
     227             :   const uint8_t* u_plane =
     228           0 :       src.DataU() + src.StrideU() * uv_offset_y + uv_offset_x;
     229             :   const uint8_t* v_plane =
     230           0 :       src.DataV() + src.StrideV() * uv_offset_y + uv_offset_x;
     231           0 :   int res = libyuv::I420Scale(y_plane, src.StrideY(),
     232           0 :                               u_plane, src.StrideU(),
     233           0 :                               v_plane, src.StrideV(),
     234             :                               crop_width, crop_height,
     235           0 :                               MutableDataY(), StrideY(),
     236           0 :                               MutableDataU(), StrideU(),
     237           0 :                               MutableDataV(), StrideV(),
     238           0 :                               width(), height(), libyuv::kFilterBox);
     239             : 
     240           0 :   RTC_DCHECK_EQ(res, 0);
     241           0 : }
     242             : 
     243           0 : void I420Buffer::CropAndScaleFrom(
     244             :     const VideoFrameBuffer& src) {
     245             :   const int crop_width =
     246           0 :       std::min(src.width(), width() * src.height() / height());
     247             :   const int crop_height =
     248           0 :       std::min(src.height(), height() * src.width() / width());
     249             : 
     250           0 :   CropAndScaleFrom(
     251             :       src,
     252           0 :       (src.width() - crop_width) / 2, (src.height() - crop_height) / 2,
     253           0 :       crop_width, crop_height);
     254           0 : }
     255             : 
     256           0 : void I420Buffer::ScaleFrom(const VideoFrameBuffer& src) {
     257           0 :   CropAndScaleFrom(src, 0, 0, src.width(), src.height());
     258           0 : }
     259             : 
     260             : }  // namespace webrtc

Generated by: LCOV version 1.13