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