1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11026d1ce6fc5608190aa5fd48f51278c60515c093pbos@webrtc.org#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <assert.h>
143bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org#include <string.h>
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
16266fc69742dbcff7e1f46e2960470feb1a98650candrew@webrtc.org// NOTE(ajm): Path provided by gyp.
17266fc69742dbcff7e1f46e2960470feb1a98650candrew@webrtc.org#include "libyuv.h"  // NOLINT
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
217012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.orgconst int k16ByteAlignment = 16;
227012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.org
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgVideoType RawVideoTypeToCommonVideoVideoType(RawVideoType type) {
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (type) {
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoI420:
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kI420;
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoIYUV:
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kIYUV;
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoRGB24:
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kRGB24;
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoARGB:
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kARGB;
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoARGB4444:
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kARGB4444;
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoRGB565:
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kRGB565;
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoARGB1555:
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kARGB1555;
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoYUY2:
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kYUY2;
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoYV12:
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kYV12;
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoUYVY:
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kUYVY;
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoNV21:
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kNV21;
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoNV12:
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kNV12;
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoBGRA:
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kBGRA;
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVideoMJPEG:
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return kMJPG;
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      assert(false);
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return kUnknown;
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint AlignInt(int value, int alignment) {
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(!((alignment - 1) & alignment));
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return ((value + alignment - 1) & ~ (alignment - 1));
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
647012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.orgvoid Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) {
657012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.org  *stride_y = AlignInt(width, k16ByteAlignment);
667012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.org  *stride_uv = AlignInt((width + 1) / 2, k16ByteAlignment);
677012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.org}
687012d2b0a89b5697dea51f17643bd40f2552a601mikhal@webrtc.org
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint CalcBufferSize(VideoType type, int width, int height) {
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int buffer_size = 0;
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (type) {
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kI420:
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kNV12:
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kNV21:
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIYUV:
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kYV12: {
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      int half_width = (width + 1) >> 1;
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      int half_height = (height + 1) >> 1;
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      buffer_size = width * height + half_width * half_height * 2;
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kARGB4444:
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRGB565:
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kARGB1555:
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kYUY2:
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kUYVY:
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      buffer_size = width * height * 2;
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRGB24:
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      buffer_size = width * height * 3;
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kBGRA:
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kARGB:
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      buffer_size = width * height * 4;
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      break;
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      assert(false);
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return buffer_size;
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1033bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgint PrintI420VideoFrame(const I420VideoFrame& frame, FILE* file) {
1043bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  if (file == NULL)
1053bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    return -1;
1063bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  if (frame.IsZeroSize())
1073bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    return -1;
1083bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  for (int planeNum = 0; planeNum < kNumOfPlanes; ++planeNum) {
1093bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    int width = (planeNum ? (frame.width() + 1) / 2 : frame.width());
1103bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    int height = (planeNum ? (frame.height() + 1) / 2 : frame.height());
1113bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    PlaneType plane_type = static_cast<PlaneType>(planeNum);
1123bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    const uint8_t* plane_buffer = frame.buffer(plane_type);
1133bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    for (int y = 0; y < height; y++) {
1143bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org     if (fwrite(plane_buffer, 1, width, file) !=
1153bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org         static_cast<unsigned int>(width)) {
1163bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org       return -1;
1173bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org       }
1183bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org       plane_buffer += frame.stride(plane_type);
1193bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    }
1203bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org }
1213bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org return 0;
1223bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org}
1233bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
1243bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgint ExtractBuffer(const I420VideoFrame& input_frame,
1253bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                  int size, uint8_t* buffer) {
1263bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  assert(buffer);
1273bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  if (input_frame.IsZeroSize())
1283bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    return -1;
1293bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  int length = CalcBufferSize(kI420, input_frame.width(), input_frame.height());
1303bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  if (size < length) {
1313bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org     return -1;
1323bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  }
1333bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
1343bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  int pos = 0;
1353bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  uint8_t* buffer_ptr = buffer;
1363bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
1373bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  for (int plane = 0; plane < kNumOfPlanes; ++plane) {
1383bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    int width = (plane ? (input_frame.width() + 1) / 2 :
1393bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      input_frame.width());
1403bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    int height = (plane ? (input_frame.height() + 1) / 2 :
1413bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      input_frame.height());
1423bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    const uint8_t* plane_ptr = input_frame.buffer(
1433bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org        static_cast<PlaneType>(plane));
1443bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    for (int y = 0; y < height; y++) {
1453bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      memcpy(&buffer_ptr[pos], plane_ptr, width);
1463bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      pos += width;
1473bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      plane_ptr += input_frame.stride(static_cast<PlaneType>(plane));
1483bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org    }
1493bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  }
1503bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  return length;
1513bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org}
1523bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
1533bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ConvertNV12ToRGB565(const uint8_t* src_frame,
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        uint8_t* dst_frame,
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int width, int height) {
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int abs_height = (height < 0) ? -height : height;
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const uint8_t* yplane = src_frame;
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const uint8_t* uvInterlaced = src_frame + (width * abs_height);
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return libyuv::NV12ToRGB565(yplane, width,
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              uvInterlaced, (width + 1) >> 1,
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              dst_frame, width,
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              width, height);
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ConvertRGB24ToARGB(const uint8_t* src_frame, uint8_t* dst_frame,
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       int width, int height, int dst_stride) {
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (dst_stride == 0)
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    dst_stride = width;
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return libyuv::RGB24ToARGB(src_frame, width,
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             dst_frame, dst_stride,
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             width, height);
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orglibyuv::RotationMode ConvertRotationMode(VideoRotationMode rotation) {
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch(rotation) {
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRotateNone:
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::kRotate0;
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRotate90:
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::kRotate90;
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRotate180:
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::kRotate180;
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRotate270:
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::kRotate270;
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(false);
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return libyuv::kRotate0;
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ConvertVideoType(VideoType video_type) {
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch(video_type) {
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kUnknown:
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_ANY;
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case  kI420:
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_I420;
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kIYUV:  // same as KYV12
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kYV12:
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_YV12;
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRGB24:
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_24BG;
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kABGR:
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_ABGR;
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kRGB565:
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_RGBP;
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kYUY2:
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_YUY2;
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kUYVY:
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_UYVY;
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kMJPG:
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_MJPG;
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kNV21:
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_NV21;
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kNV12:
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_NV12;
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kARGB:
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_ARGB;
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kBGRA:
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_BGRA;
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kARGB4444:
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_R444;
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kARGB1555:
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return libyuv::FOURCC_RGBO;
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(false);
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return libyuv::FOURCC_ANY;
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ConvertToI420(VideoType src_video_type,
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  const uint8_t* src_frame,
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  int crop_x, int crop_y,
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  int src_width, int src_height,
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  int sample_size,
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  VideoRotationMode rotation,
2353bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                  I420VideoFrame* dst_frame) {
2365be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org  int dst_width = dst_frame->width();
2375be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org  int dst_height = dst_frame->height();
2385be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org  // LibYuv expects pre-rotation values for dst.
2395be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org  // Stride values should correspond to the destination values.
2405be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org  if (rotation == kRotate90 || rotation == kRotate270) {
2415be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org    dst_width = dst_frame->height();
2425be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org    dst_height =dst_frame->width();
2435be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org  }
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return libyuv::ConvertToI420(src_frame, sample_size,
2453bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                               dst_frame->buffer(kYPlane),
2463bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                               dst_frame->stride(kYPlane),
2473bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                               dst_frame->buffer(kUPlane),
2483bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                               dst_frame->stride(kUPlane),
2493bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                               dst_frame->buffer(kVPlane),
2503bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                               dst_frame->stride(kVPlane),
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               crop_x, crop_y,
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               src_width, src_height,
2535be3165fad82f4b8b5d986fa567dde21584a13f8mikhal@webrtc.org                               dst_width, dst_height,
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               ConvertRotationMode(rotation),
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               ConvertVideoType(src_video_type));
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2583bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgint ConvertFromI420(const I420VideoFrame& src_frame,
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    VideoType dst_video_type, int dst_sample_size,
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    uint8_t* dst_frame) {
2613bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  return libyuv::ConvertFromI420(src_frame.buffer(kYPlane),
2623bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.stride(kYPlane),
2633bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.buffer(kUPlane),
2643bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.stride(kUPlane),
2653bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.buffer(kVPlane),
2663bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.stride(kVPlane),
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 dst_frame, dst_sample_size,
2683bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.width(), src_frame.height(),
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ConvertVideoType(dst_video_type));
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2723bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org// TODO(mikhal): Create a designated VideoFrame for non I420.
2733bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgint ConvertFromYV12(const I420VideoFrame& src_frame,
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    VideoType dst_video_type, int dst_sample_size,
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    uint8_t* dst_frame) {
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // YV12 = Y, V, U
2773bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  return libyuv::ConvertFromI420(src_frame.buffer(kYPlane),
2783bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.stride(kYPlane),
2793bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.buffer(kVPlane),
2803bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.stride(kVPlane),
2813bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.buffer(kUPlane),
2823bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.stride(kUPlane),
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 dst_frame, dst_sample_size,
2843bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 src_frame.width(), src_frame.height(),
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                 ConvertVideoType(dst_video_type));
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
2883bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgint MirrorI420LeftRight(const I420VideoFrame* src_frame,
2893bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                        I420VideoFrame* dst_frame) {
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Source and destination frames should have equal resolution.
2913bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  if (src_frame->width() != dst_frame->width() ||
2923bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      src_frame->height() != dst_frame->height())
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
2943bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  return libyuv::I420Mirror(src_frame->buffer(kYPlane),
2953bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            src_frame->stride(kYPlane),
2963bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            src_frame->buffer(kUPlane),
2973bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            src_frame->stride(kUPlane),
2983bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            src_frame->buffer(kVPlane),
2993bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            src_frame->stride(kVPlane),
3003bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            dst_frame->buffer(kYPlane),
3013bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            dst_frame->stride(kYPlane),
3023bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            dst_frame->buffer(kUPlane),
3033bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            dst_frame->stride(kUPlane),
3043bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            dst_frame->buffer(kVPlane),
3053bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            dst_frame->stride(kVPlane),
3063bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                            src_frame->width(), src_frame->height());
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3093bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgint MirrorI420UpDown(const I420VideoFrame* src_frame,
3103bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                     I420VideoFrame* dst_frame) {
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Source and destination frames should have equal resolution
3123bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  if (src_frame->width() != dst_frame->width() ||
3133bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org      src_frame->height() != dst_frame->height())
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Inserting negative height flips the frame.
3173bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  return libyuv::I420Copy(src_frame->buffer(kYPlane),
3183bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          src_frame->stride(kYPlane),
3193bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          src_frame->buffer(kUPlane),
3203bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          src_frame->stride(kUPlane),
3213bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          src_frame->buffer(kVPlane),
3223bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          src_frame->stride(kVPlane),
3233bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          dst_frame->buffer(kYPlane),
3243bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          dst_frame->stride(kYPlane),
3253bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          dst_frame->buffer(kUPlane),
3263bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          dst_frame->stride(kUPlane),
3273bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          dst_frame->buffer(kVPlane),
3283bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          dst_frame->stride(kVPlane),
3293bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          src_frame->width(), -(src_frame->height()));
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Compute PSNR for an I420 frame (all planes)
3333bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgdouble I420PSNR(const I420VideoFrame* ref_frame,
3343bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                const I420VideoFrame* test_frame) {
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!ref_frame || !test_frame)
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
3373bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  else if ((ref_frame->width() !=  test_frame->width()) ||
3383bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org          (ref_frame->height() !=  test_frame->height()))
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
3403bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  else if (ref_frame->width() < 0 || ref_frame->height() < 0)
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
3423bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
3433bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  double psnr = libyuv::I420Psnr(ref_frame->buffer(kYPlane),
3443bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 ref_frame->stride(kYPlane),
3453bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 ref_frame->buffer(kUPlane),
3463bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 ref_frame->stride(kUPlane),
3473bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 ref_frame->buffer(kVPlane),
3483bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 ref_frame->stride(kVPlane),
3493bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->buffer(kYPlane),
3503bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->stride(kYPlane),
3513bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->buffer(kUPlane),
3523bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->stride(kUPlane),
3533bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->buffer(kVPlane),
3543bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->stride(kVPlane),
3553bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                                 test_frame->width(), test_frame->height());
3565600f6e86d3994726249fd1c77377c1d8534f107phoglund@webrtc.org  // LibYuv sets the max psnr value to 128, we restrict it here.
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // In case of 0 mse in one frame, 128 can skew the results significantly.
358ecf6f810b59a3f0e51805cc656a1cffadc8a6dbbphoglund@webrtc.org  return (psnr > kPerfectPSNR) ? kPerfectPSNR : psnr;
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
3603bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Compute SSIM for an I420 frame (all planes)
3623bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgdouble I420SSIM(const I420VideoFrame* ref_frame,
3633bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                const I420VideoFrame* test_frame) {
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!ref_frame || !test_frame)
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
3663bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  else if ((ref_frame->width() !=  test_frame->width()) ||
3673bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org          (ref_frame->height() !=  test_frame->height()))
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
3693bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  else if (ref_frame->width() < 0 || ref_frame->height()  < 0)
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
3713bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org
3723bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  return libyuv::I420Ssim(ref_frame->buffer(kYPlane),
3733bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          ref_frame->stride(kYPlane),
3743bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          ref_frame->buffer(kUPlane),
3753bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          ref_frame->stride(kUPlane),
3763bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          ref_frame->buffer(kVPlane),
3773bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          ref_frame->stride(kVPlane),
3783bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->buffer(kYPlane),
3793bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->stride(kYPlane),
3803bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->buffer(kUPlane),
3813bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->stride(kUPlane),
3823bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->buffer(kVPlane),
3833bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->stride(kVPlane),
3843bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                          test_frame->width(), test_frame->height());
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
387