1 /*
2  *  Copyright (c) 2012 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 
11 /*
12  * WebRTC's wrapper to libyuv.
13  */
14 
15 #ifndef COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_
16 #define COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_
17 
18 #include <stdio.h>
19 #include <vector>
20 
21 #include "api/video/video_frame.h"
22 #include "common_types.h"  // NOLINT(build/include)  // VideoTypes.
23 #include "typedefs.h"  // NOLINT(build/include)
24 
25 namespace webrtc {
26 
27 
28 // This is the max PSNR value our algorithms can return.
29 const double kPerfectPSNR = 48.0f;
30 
31 // TODO(nisse): Some downstream apps call CalcBufferSize with
32 // ::webrtc::kI420 as the first argument. Delete after they are updated.
33 const VideoType kI420 = VideoType::kI420;
34 
35 // Calculate the required buffer size.
36 // Input:
37 //   - type         :The type of the designated video frame.
38 //   - width        :frame width in pixels.
39 //   - height       :frame height in pixels.
40 // Return value:    :The required size in bytes to accommodate the specified
41 //                   video frame.
42 size_t CalcBufferSize(VideoType type, int width, int height);
43 
44 // TODO(mikhal): Add unit test for these two functions and determine location.
45 // Print VideoFrame to file
46 // Input:
47 //    - frame       : Reference to video frame.
48 //    - file        : pointer to file object. It is assumed that the file is
49 //                    already open for writing.
50 // Return value: 0 if OK, < 0 otherwise.
51 int PrintVideoFrame(const VideoFrame& frame, FILE* file);
52 int PrintVideoFrame(const I420BufferInterface& frame, FILE* file);
53 
54 // Extract buffer from VideoFrame or I420BufferInterface (consecutive
55 // planes, no stride)
56 // Input:
57 //   - frame       : Reference to video frame.
58 //   - size        : pointer to the size of the allocated buffer. If size is
59 //                   insufficient, an error will be returned.
60 //   - buffer      : Pointer to buffer
61 // Return value: length of buffer if OK, < 0 otherwise.
62 int ExtractBuffer(const rtc::scoped_refptr<I420BufferInterface>& input_frame,
63                   size_t size,
64                   uint8_t* buffer);
65 int ExtractBuffer(const VideoFrame& input_frame, size_t size, uint8_t* buffer);
66 // Convert From I420
67 // Input:
68 //   - src_frame        : Reference to a source frame.
69 //   - dst_video_type   : Type of output video.
70 //   - dst_sample_size  : Required only for the parsing of MJPG.
71 //   - dst_frame        : Pointer to a destination frame.
72 // Return value: 0 if OK, < 0 otherwise.
73 // It is assumed that source and destination have equal height.
74 int ConvertFromI420(const VideoFrame& src_frame,
75                     VideoType dst_video_type,
76                     int dst_sample_size,
77                     uint8_t* dst_frame);
78 
79 // Compute PSNR for an I420 frame (all planes).
80 // Returns the PSNR in decibel, to a maximum of kInfinitePSNR.
81 double I420PSNR(const VideoFrame* ref_frame, const VideoFrame* test_frame);
82 double I420PSNR(const I420BufferInterface& ref_buffer,
83                 const I420BufferInterface& test_buffer);
84 
85 // Compute SSIM for an I420 frame (all planes).
86 double I420SSIM(const VideoFrame* ref_frame, const VideoFrame* test_frame);
87 double I420SSIM(const I420BufferInterface& ref_buffer,
88                 const I420BufferInterface& test_buffer);
89 
90 // Helper function for scaling NV12 to NV12.
91 // If the |src_width| and |src_height| matches the |dst_width| and |dst_height|,
92 // then |tmp_buffer| is not used. In other cases, the minimum size of
93 // |tmp_buffer| should be:
94 //   (src_width/2) * (src_height/2) * 2 + (dst_width/2) * (dst_height/2) * 2
95 void NV12Scale(uint8_t* tmp_buffer,
96                const uint8_t* src_y, int src_stride_y,
97                const uint8_t* src_uv, int src_stride_uv,
98                int src_width, int src_height,
99                uint8_t* dst_y, int dst_stride_y,
100                uint8_t* dst_uv, int dst_stride_uv,
101                int dst_width, int dst_height);
102 
103 // Helper class for directly converting and scaling NV12 to I420. The Y-plane
104 // will be scaled directly to the I420 destination, which makes this faster
105 // than separate NV12->I420 + I420->I420 scaling.
106 class NV12ToI420Scaler {
107  public:
108   NV12ToI420Scaler();
109   ~NV12ToI420Scaler();
110   void NV12ToI420Scale(const uint8_t* src_y, int src_stride_y,
111                        const uint8_t* src_uv, int src_stride_uv,
112                        int src_width, int src_height,
113                        uint8_t* dst_y, int dst_stride_y,
114                        uint8_t* dst_u, int dst_stride_u,
115                        uint8_t* dst_v, int dst_stride_v,
116                        int dst_width, int dst_height);
117  private:
118   std::vector<uint8_t> tmp_uv_planes_;
119 };
120 
121 // Convert VideoType to libyuv FourCC type
122 int ConvertVideoType(VideoType video_type);
123 
124 }  // namespace webrtc
125 
126 #endif  // COMMON_VIDEO_LIBYUV_INCLUDE_WEBRTC_LIBYUV_H_
127