Implement I010ToNV12 conversion

I010, also known as YUV420P10, is 10 bit YUV pixel format with 3 planes.
Both I010 and NV12 are 4:2:0 subsampling. NV12 has a Y plane, and an
interleaved UV plane.

Bug: 357721018
Change-Id: If215529b9eda8e0fb32aed666ca179c90244aaff
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/5764823
Reviewed-by: Frank Barchard <fbarchard@chromium.org>
diff --git a/include/libyuv/convert.h b/include/libyuv/convert.h
index 7802f59..5c7669b 100644
--- a/include/libyuv/convert.h
+++ b/include/libyuv/convert.h
@@ -525,6 +525,21 @@
                int width,
                int height);
 
+// Convert 10 bit YUV I010 to NV12
+LIBYUV_API
+int I010ToNV12(const uint16_t* src_y,
+               int src_stride_y,
+               const uint16_t* src_u,
+               int src_stride_u,
+               const uint16_t* src_v,
+               int src_stride_v,
+               uint8_t* dst_y,
+               int dst_stride_y,
+               uint8_t* dst_uv,
+               int dst_stride_uv,
+               int width,
+               int height);
+
 // Convert I210 to P210
 LIBYUV_API
 int I210ToP210(const uint16_t* src_y,
diff --git a/source/convert.cc b/source/convert.cc
index 000d6fe..83f7806 100644
--- a/source/convert.cc
+++ b/source/convert.cc
@@ -646,6 +646,55 @@
 }
 
 LIBYUV_API
+int I010ToNV12(const uint16_t* src_y,
+               int src_stride_y,
+               const uint16_t* src_u,
+               int src_stride_u,
+               const uint16_t* src_v,
+               int src_stride_v,
+               uint8_t* dst_y,
+               int dst_stride_y,
+               uint8_t* dst_uv,
+               int dst_stride_uv,
+               int width,
+               int height) {
+  // Allocate temporary buffers for 3 planes in 8 bit.
+  uint8_t* temp_y = (uint8_t*)malloc(width * height);
+  uint8_t* temp_u = (uint8_t*)malloc((width / 2) * (height / 2));
+  uint8_t* temp_v = (uint8_t*)malloc((width / 2) * (height / 2));
+  int temp_stride_y = width;
+  int temp_stride_u = width / 2;
+  int temp_stride_v = width / 2;
+
+  // The first step is to convert 10 bit YUV I010 to 8 bit I420 with 3 planes.
+  if (I010ToI420(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
+                 temp_y, temp_stride_y, temp_u, temp_stride_u, temp_v,
+                 temp_stride_v, width, height) == -1) {
+    free(temp_y);
+    free(temp_u);
+    free(temp_v);
+    return -1;
+  }
+
+  // The second step is to convert 8 bit I420 with 3 planes to 8 bit NV12 with 2 planes.
+  if (I420ToNV12(temp_y, temp_stride_y, temp_u, temp_stride_u, temp_v,
+                 temp_stride_v, dst_y, dst_stride_y, dst_uv, dst_stride_uv,
+                 width, height) == -1) {
+    free(temp_y);
+    free(temp_u);
+    free(temp_v);
+    return -1;
+  }
+
+  // Free temporary buffers.
+  free(temp_y);
+  free(temp_u);
+  free(temp_v);
+
+  return 0;
+}
+
+LIBYUV_API
 int I210ToP210(const uint16_t* src_y,
                int src_stride_y,
                const uint16_t* src_u,