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/interface/i420_video_frame.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
131bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org#include <string.h>
141bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <algorithm>  // swap
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgI420VideoFrame::I420VideoFrame()
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    : width_(0),
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      height_(0),
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      timestamp_(0),
239d10769e109601915022fea44ec392645c3b0704wu@webrtc.org      ntp_time_ms_(0),
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      render_time_ms_(0) {}
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgI420VideoFrame::~I420VideoFrame() {}
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::CreateEmptyFrame(int width, int height,
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                     int stride_y, int stride_u, int stride_v) {
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CheckDimensions(width, height, stride_y, stride_u, stride_v) < 0)
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int size_y = stride_y * height;
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int half_height = (height + 1) / 2;
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int size_u = stride_u * half_height;
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int size_v = stride_v * half_height;
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  width_ = width;
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  height_ = height;
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  y_plane_.CreateEmptyPlane(size_y, stride_y, size_y);
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  u_plane_.CreateEmptyPlane(size_u, stride_u, size_u);
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  v_plane_.CreateEmptyPlane(size_v, stride_v, size_v);
413bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  // Creating empty frame - reset all values.
423bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  timestamp_ = 0;
439d10769e109601915022fea44ec392645c3b0704wu@webrtc.org  ntp_time_ms_ = 0;
443bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  render_time_ms_ = 0;
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::CreateFrame(int size_y, const uint8_t* buffer_y,
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int size_u, const uint8_t* buffer_u,
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int size_v, const uint8_t* buffer_v,
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int width, int height,
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                int stride_y, int stride_u, int stride_v) {
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (size_y < 1 || size_u < 1 || size_v < 1)
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CheckDimensions(width, height, stride_y, stride_u, stride_v) < 0)
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  y_plane_.Copy(size_y, stride_y, buffer_y);
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  u_plane_.Copy(size_u, stride_u, buffer_u);
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  v_plane_.Copy(size_v, stride_v, buffer_v);
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  width_ = width;
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  height_ = height;
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::CopyFrame(const I420VideoFrame& videoFrame) {
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int ret = CreateFrame(videoFrame.allocated_size(kYPlane),
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.buffer(kYPlane),
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.allocated_size(kUPlane),
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.buffer(kUPlane),
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.allocated_size(kVPlane),
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.buffer(kVPlane),
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.width_, videoFrame.height_,
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.stride(kYPlane), videoFrame.stride(kUPlane),
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        videoFrame.stride(kVPlane));
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (ret < 0)
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return ret;
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  timestamp_ = videoFrame.timestamp_;
789d10769e109601915022fea44ec392645c3b0704wu@webrtc.org  ntp_time_ms_ = videoFrame.ntp_time_ms_;
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  render_time_ms_ = videoFrame.render_time_ms_;
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
831bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.orgI420VideoFrame* I420VideoFrame::CloneFrame() const {
841bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org  scoped_ptr<I420VideoFrame> new_frame(new I420VideoFrame());
851bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org  if (new_frame->CopyFrame(*this) == -1) {
861bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org    // CopyFrame failed.
871bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org    return NULL;
881bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org  }
891bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org  return new_frame.release();
901bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org}
911bdf186e6ae8d2f1a7d055237a75c0d7fd189624wuchengli@chromium.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid I420VideoFrame::SwapFrame(I420VideoFrame* videoFrame) {
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  y_plane_.Swap(videoFrame->y_plane_);
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  u_plane_.Swap(videoFrame->u_plane_);
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  v_plane_.Swap(videoFrame->v_plane_);
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::swap(width_, videoFrame->width_);
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::swap(height_, videoFrame->height_);
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::swap(timestamp_, videoFrame->timestamp_);
999d10769e109601915022fea44ec392645c3b0704wu@webrtc.org  std::swap(ntp_time_ms_, videoFrame->ntp_time_ms_);
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::swap(render_time_ms_, videoFrame->render_time_ms_);
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orguint8_t* I420VideoFrame::buffer(PlaneType type) {
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Plane* plane_ptr = GetPlane(type);
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (plane_ptr)
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return plane_ptr->buffer();
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return NULL;
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst uint8_t* I420VideoFrame::buffer(PlaneType type) const {
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const Plane* plane_ptr = GetPlane(type);
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (plane_ptr)
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return plane_ptr->buffer();
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return NULL;
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::allocated_size(PlaneType type) const {
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const Plane* plane_ptr = GetPlane(type);
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (plane_ptr)
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return plane_ptr->allocated_size();
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return -1;
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::stride(PlaneType type) const {
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const Plane* plane_ptr = GetPlane(type);
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (plane_ptr)
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return plane_ptr->stride();
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return -1;
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::set_width(int width) {
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CheckDimensions(width, height_,
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      y_plane_.stride(), u_plane_.stride(),
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      v_plane_.stride()) < 0)
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  width_ = width;
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::set_height(int height) {
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (CheckDimensions(width_, height,
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      y_plane_.stride(), u_plane_.stride(),
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                      v_plane_.stride()) < 0)
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  height_ = height;
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1493bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.orgbool I420VideoFrame::IsZeroSize() const {
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return (y_plane_.IsZeroSize() && u_plane_.IsZeroSize() &&
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    v_plane_.IsZeroSize());
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid I420VideoFrame::ResetSize() {
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  y_plane_.ResetSize();
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  u_plane_.ResetSize();
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  v_plane_.ResetSize();
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
160ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.orgvoid* I420VideoFrame::native_handle() const { return NULL; }
161ea7b33ee032bd2d1528384e26ba079dee0d280fbwu@webrtc.org
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint I420VideoFrame::CheckDimensions(int width, int height,
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                    int stride_y, int stride_u, int stride_v) {
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int half_width = (width + 1) / 2;
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (width < 1 || height < 1 ||
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      stride_y < width || stride_u < half_width || stride_v < half_width)
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgconst Plane* I420VideoFrame::GetPlane(PlaneType type) const {
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (type) {
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kYPlane :
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return &y_plane_;
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kUPlane :
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return &u_plane_;
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVPlane :
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return &v_plane_;
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      assert(false);
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return NULL;
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgPlane* I420VideoFrame::GetPlane(PlaneType type) {
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  switch (type) {
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kYPlane :
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return &y_plane_;
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kUPlane :
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return &u_plane_;
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    case kVPlane :
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return &v_plane_;
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    default:
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      assert(false);
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return NULL;
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
200