diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index 9e54a75c98..9fb1d08951 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -2277,7 +2277,85 @@ GST_VIDEO_BUFFER_TFF GST_VIDEO_BUFFER_RFF GST_VIDEO_BUFFER_ONEFIELD GST_VIDEO_BUFFER_PROGRESSIVE +GstVideoChromaSite +GstVideoColorMatrix +GstVideoColorPrimaries +GstVideoColorRange +GstVideoColorimetry +GstVideoFlags +GstVideoFormatFlags +GstVideoFormatPack +GstVideoFormatUnpack +GstVideoInterlaceMode +GstVideoTransferFunction GstVideoFormat +GstVideoFormatInfo +GST_VIDEO_FORMAT_INFO_BITS +GST_VIDEO_FORMAT_INFO_DATA +GST_VIDEO_FORMAT_INFO_DEPTH +GST_VIDEO_FORMAT_INFO_FLAGS +GST_VIDEO_FORMAT_INFO_FORMAT +GST_VIDEO_FORMAT_INFO_HAS_ALPHA +GST_VIDEO_FORMAT_INFO_HAS_PALETTE +GST_VIDEO_FORMAT_INFO_H_SUB +GST_VIDEO_FORMAT_INFO_IS_GRAY +GST_VIDEO_FORMAT_INFO_IS_LE +GST_VIDEO_FORMAT_INFO_IS_RGB +GST_VIDEO_FORMAT_INFO_IS_YUV +GST_VIDEO_FORMAT_INFO_NAME +GST_VIDEO_FORMAT_INFO_N_COMPONENTS +GST_VIDEO_FORMAT_INFO_N_PLANES +GST_VIDEO_FORMAT_INFO_OFFSET +GST_VIDEO_FORMAT_INFO_PLANE +GST_VIDEO_FORMAT_INFO_POFFSET +GST_VIDEO_FORMAT_INFO_PSTRIDE +GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT +GST_VIDEO_FORMAT_INFO_SCALE_WIDTH +GST_VIDEO_FORMAT_INFO_SHIFT +GST_VIDEO_FORMAT_INFO_STRIDE +GST_VIDEO_FORMAT_INFO_W_SUB +GstVideoInfo +GST_VIDEO_INFO_COMP_BITS +GST_VIDEO_INFO_COMP_DATA +GST_VIDEO_INFO_COMP_DEPTH +GST_VIDEO_INFO_COMP_HEIGHT +GST_VIDEO_INFO_COMP_OFFSET +GST_VIDEO_INFO_COMP_PLANE +GST_VIDEO_INFO_COMP_POFFSET +GST_VIDEO_INFO_COMP_PSTRIDE +GST_VIDEO_INFO_COMP_STRIDE +GST_VIDEO_INFO_COMP_WIDTH +GST_VIDEO_INFO_FLAGS +GST_VIDEO_INFO_FLAG_IS_SET +GST_VIDEO_INFO_FLAG_SET +GST_VIDEO_INFO_FLAG_UNSET +GST_VIDEO_INFO_FORMAT +GST_VIDEO_INFO_FPS_D +GST_VIDEO_INFO_FPS_N +GST_VIDEO_INFO_HAS_ALPHA +GST_VIDEO_INFO_HEIGHT +GST_VIDEO_INFO_INTERLACE_MODE +GST_VIDEO_INFO_IS_GRAY +GST_VIDEO_INFO_IS_INTERLACED +GST_VIDEO_INFO_IS_RGB +GST_VIDEO_INFO_IS_YUV +GST_VIDEO_INFO_NAME +GST_VIDEO_INFO_N_COMPONENTS +GST_VIDEO_INFO_N_PLANES +GST_VIDEO_INFO_PAR_D +GST_VIDEO_INFO_PAR_N +GST_VIDEO_INFO_PLANE_OFFSET +GST_VIDEO_INFO_PLANE_STRIDE +GST_VIDEO_INFO_SIZE +GST_VIDEO_INFO_WIDTH +GST_VIDEO_MAX_COMPONENTS +GST_VIDEO_MAX_PLANES +GST_VIDEO_SUB_SCALE +gst_video_info_convert +gst_video_info_from_caps +gst_video_info_init +gst_video_info_set_format +gst_video_info_to_caps gst_video_calculate_display_ratio gst_video_frame_rate gst_video_get_size @@ -2293,12 +2371,15 @@ gst_video_format_get_component_depth gst_video_format_get_pixel_stride gst_video_format_get_row_stride gst_video_format_get_size +gst_video_format_get_info gst_video_format_has_alpha gst_video_format_is_rgb gst_video_format_is_gray gst_video_format_is_yuv gst_video_format_to_fourcc gst_video_format_from_fourcc +gst_video_format_to_string +gst_video_format_from_masks gst_video_format_parse_caps gst_video_format_parse_caps_interlaced gst_video_parse_caps_framerate @@ -2306,6 +2387,9 @@ gst_video_parse_caps_pixel_aspect_ratio gst_video_parse_caps_color_matrix gst_video_parse_caps_chroma_site gst_video_parse_caps_palette +gst_video_colorimetry_from_string +gst_video_colorimetry_matches +gst_video_colorimetry_to_string GstVideoConvertFrameCallback gst_video_convert_frame gst_video_convert_frame_async @@ -2319,6 +2403,22 @@ gst_video_event_parse_downstream_force_key_unit gst_video_format_get_type GST_TYPE_VIDEO_FORMAT +GST_TYPE_VIDEO_CHROMA_SITE +GST_TYPE_VIDEO_COLOR_MATRIX +GST_TYPE_VIDEO_COLOR_PRIMARIES +GST_TYPE_VIDEO_COLOR_RANGE +GST_TYPE_VIDEO_FLAGS +GST_TYPE_VIDEO_FORMAT_FLAGS +GST_TYPE_VIDEO_INTERLACE_MODE +GST_TYPE_VIDEO_TRANSFER_FUNCTION +gst_video_chroma_site_get_type +gst_video_color_matrix_get_type +gst_video_color_primaries_get_type +gst_video_color_range_get_type +gst_video_flags_get_type +gst_video_format_flags_get_type +gst_video_interlace_mode_get_type +gst_video_transfer_function_get_type
diff --git a/gst-libs/gst/video/video.c b/gst-libs/gst/video/video.c index f68de1ce4e..1922832bbb 100644 --- a/gst-libs/gst/video/video.c +++ b/gst-libs/gst/video/video.c @@ -23,6 +23,7 @@ # include "config.h" #endif +#include #include "video.h" /** @@ -47,6 +48,218 @@ static GstVideoFormat gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask); +static int fill_planes (GstVideoInfo * info); + +typedef struct +{ + guint32 fourcc; + GstVideoFormatInfo info; +} VideoFormat; + +/* depths: bits, n_components, shift, depth */ +#define DPTH0 0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } +#define DPTH8 8, 1, { 0, 0, 0, 0 }, { 8, 0, 0, 0 } +#define DPTH888 8, 3, { 0, 0, 0, 0 }, { 8, 8, 8, 0 } +#define DPTH8888 8, 4, { 0, 0, 0, 0 }, { 8, 8, 8, 8 } +#define DPTH10_10_10 10, 3, { 0, 0, 0, 0 }, { 10, 10, 10, 0 } +#define DPTH16 16, 1, { 0, 0, 0, 0 }, { 16, 0, 0, 0 } +#define DPTH16_16_16 16, 3, { 0, 0, 0, 0 }, { 16, 16, 16, 0 } +#define DPTH16_16_16_16 16, 4, { 0, 0, 0, 0 }, { 16, 16, 16, 16 } +#define DPTH555 16, 3, { 10, 5, 0, 0 }, { 5, 5, 5, 0 } +#define DPTH565 16, 3, { 11, 5, 0, 0 }, { 5, 6, 5, 0 } + +/* pixel strides */ +#define PSTR0 { 0, 0, 0, 0 } +#define PSTR1 { 1, 0, 0, 0 } +#define PSTR111 { 1, 1, 1, 0 } +#define PSTR1111 { 1, 1, 1, 1 } +#define PSTR122 { 1, 2, 2, 0 } +#define PSTR2 { 2, 0, 0, 0 } +#define PSTR222 { 2, 2, 2, 0 } +#define PSTR244 { 2, 4, 4, 0 } +#define PSTR444 { 4, 4, 4, 0 } +#define PSTR4444 { 4, 4, 4, 4 } +#define PSTR333 { 3, 3, 3, 0 } +#define PSTR488 { 4, 8, 8, 0 } +#define PSTR8888 { 8, 8, 8, 8 } + +/* planes */ +#define PLANE_NA 0, { 0, 0, 0, 0 } +#define PLANE0 1, { 0, 0, 0, 0 } +#define PLANE011 2, { 0, 1, 1, 0 } +#define PLANE012 3, { 0, 1, 2, 0 } +#define PLANE0123 4, { 0, 1, 2, 3 } +#define PLANE021 3, { 0, 2, 1, 0 } + +/* offsets */ +#define OFFS0 { 0, 0, 0, 0 } +#define OFFS013 { 0, 1, 3, 0 } +#define OFFS102 { 1, 0, 2, 0 } +#define OFFS1230 { 1, 2, 3, 0 } +#define OFFS012 { 0, 1, 2, 0 } +#define OFFS210 { 2, 1, 0, 0 } +#define OFFS123 { 1, 2, 3, 0 } +#define OFFS321 { 3, 2, 1, 0 } +#define OFFS0123 { 0, 1, 2, 3 } +#define OFFS2103 { 2, 1, 0, 3 } +#define OFFS3210 { 3, 2, 1, 0 } +#define OFFS031 { 0, 3, 1, 0 } +#define OFFS026 { 0, 2, 6, 0 } +#define OFFS001 { 0, 0, 1, 0 } +#define OFFS010 { 0, 1, 0, 0 } +#define OFFS104 { 1, 0, 4, 0 } +#define OFFS2460 { 2, 4, 6, 0 } + +/* subsampling */ +#define SUB410 { 0, 2, 2, 0 }, { 0, 2, 2, 0 } +#define SUB411 { 0, 2, 2, 0 }, { 0, 0, 0, 0 } +#define SUB420 { 0, 1, 1, 0 }, { 0, 1, 1, 0 } +#define SUB422 { 0, 1, 1, 0 }, { 0, 0, 0, 0 } +#define SUB4 { 0, 0, 0, 0 }, { 0, 0, 0, 0 } +#define SUB444 { 0, 0, 0, 0 }, { 0, 0, 0, 0 } +#define SUB4444 { 0, 0, 0, 0 }, { 0, 0, 0, 0 } +#define SUB4204 { 0, 1, 1, 0 }, { 0, 1, 1, 0 } + +#define MAKE_YUV_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub ) \ + { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV, depth, pstride, plane, offs, sub } } +#define MAKE_YUVA_FORMAT(name, desc, fourcc, depth, pstride, plane, offs, sub) \ + { fourcc, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_YUV | GST_VIDEO_FORMAT_FLAG_ALPHA, depth, pstride, plane, offs, sub } } + +#define MAKE_RGB_FORMAT(name, desc, depth, pstride, plane, offs, sub) \ + { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB, depth, pstride, plane, offs, sub } } +#define MAKE_RGB_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub) \ + { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub } } +#define MAKE_RGBA_FORMAT(name, desc, depth, pstride, plane, offs, sub) \ + { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_RGB | GST_VIDEO_FORMAT_FLAG_ALPHA, depth, pstride, plane, offs, sub } } + +#define MAKE_GRAY_FORMAT(name, desc, depth, pstride, plane, offs, sub) \ + { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY, depth, pstride, plane, offs, sub } } +#define MAKE_GRAY_LE_FORMAT(name, desc, depth, pstride, plane, offs, sub) \ + { 0x00000000, {GST_VIDEO_FORMAT_ ##name, G_STRINGIFY(name), desc, GST_VIDEO_FORMAT_FLAG_GRAY | GST_VIDEO_FORMAT_FLAG_LE, depth, pstride, plane, offs, sub } } + +static VideoFormat formats[] = { + {0x00000000, {GST_VIDEO_FORMAT_UNKNOWN, "UNKNOWN", "unknown video", 0, DPTH0, + PSTR0, PLANE_NA, + OFFS0}}, + + MAKE_YUV_FORMAT (I420, "raw video", GST_MAKE_FOURCC ('I', '4', '2', '0'), + DPTH888, PSTR111, + PLANE012, OFFS0, SUB420), + MAKE_YUV_FORMAT (YV12, "raw video", GST_MAKE_FOURCC ('Y', 'V', '1', '2'), + DPTH888, PSTR111, + PLANE021, OFFS0, SUB420), + MAKE_YUV_FORMAT (YUY2, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), + DPTH888, PSTR244, + PLANE0, OFFS013, SUB422), + MAKE_YUV_FORMAT (UYVY, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), + DPTH888, PSTR244, + PLANE0, OFFS102, SUB422), + MAKE_YUVA_FORMAT (AYUV, "raw video", GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'), + DPTH8888, + PSTR4444, PLANE0, OFFS1230, SUB4444), + MAKE_RGB_FORMAT (RGBx, "raw video", DPTH888, PSTR444, PLANE0, OFFS012, + SUB444), + MAKE_RGB_FORMAT (BGRx, "raw video", DPTH888, PSTR444, PLANE0, OFFS210, + SUB444), + MAKE_RGB_FORMAT (xRGB, "raw video", DPTH888, PSTR444, PLANE0, OFFS123, + SUB444), + MAKE_RGB_FORMAT (xBGR, "raw video", DPTH888, PSTR444, PLANE0, OFFS321, + SUB444), + MAKE_RGBA_FORMAT (RGBA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS0123, + SUB4444), + MAKE_RGBA_FORMAT (BGRA, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS2103, + SUB4444), + MAKE_RGBA_FORMAT (ARGB, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS1230, + SUB4444), + MAKE_RGBA_FORMAT (ABGR, "raw video", DPTH8888, PSTR4444, PLANE0, OFFS3210, + SUB4444), + MAKE_RGB_FORMAT (RGB, "raw video", DPTH888, PSTR333, PLANE0, OFFS012, SUB444), + MAKE_RGB_FORMAT (BGR, "raw video", DPTH888, PSTR333, PLANE0, OFFS210, SUB444), + + MAKE_YUV_FORMAT (Y41B, "raw video", GST_MAKE_FOURCC ('Y', '4', '1', 'B'), + DPTH888, PSTR111, + PLANE012, OFFS0, SUB411), + MAKE_YUV_FORMAT (Y42B, "raw video", GST_MAKE_FOURCC ('Y', '4', '2', 'B'), + DPTH888, PSTR111, + PLANE012, OFFS0, SUB422), + MAKE_YUV_FORMAT (YVYU, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'), + DPTH888, PSTR244, + PLANE0, OFFS031, SUB422), + MAKE_YUV_FORMAT (Y444, "raw video", GST_MAKE_FOURCC ('Y', '4', '4', '4'), + DPTH888, PSTR111, + PLANE012, OFFS0, SUB444), + MAKE_YUV_FORMAT (v210, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '0'), + DPTH10_10_10, + PSTR0, PLANE0, OFFS0, SUB422), + MAKE_YUV_FORMAT (v216, "raw video", GST_MAKE_FOURCC ('v', '2', '1', '6'), + DPTH16_16_16, + PSTR488, PLANE0, OFFS026, SUB422), + MAKE_YUV_FORMAT (NV12, "raw video", GST_MAKE_FOURCC ('N', 'V', '1', '2'), + DPTH888, PSTR122, + PLANE011, OFFS001, SUB420), + MAKE_YUV_FORMAT (NV21, "raw video", GST_MAKE_FOURCC ('N', 'V', '2', '1'), + DPTH888, PSTR122, + PLANE011, OFFS010, SUB420), + + MAKE_GRAY_FORMAT (GRAY8, "raw video", DPTH8, PSTR1, PLANE0, OFFS0, SUB4), + MAKE_GRAY_FORMAT (GRAY16_BE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0, SUB4), + MAKE_GRAY_LE_FORMAT (GRAY16_LE, "raw video", DPTH16, PSTR2, PLANE0, OFFS0, + SUB4), + + MAKE_YUV_FORMAT (v308, "raw video", GST_MAKE_FOURCC ('v', '3', '0', '8'), + DPTH888, PSTR333, + PLANE0, OFFS012, SUB444), + MAKE_YUV_FORMAT (Y800, "raw video", GST_MAKE_FOURCC ('Y', '8', '0', '0'), + DPTH8, PSTR1, + PLANE0, OFFS0, SUB4), + MAKE_YUV_FORMAT (Y16, "raw video", GST_MAKE_FOURCC ('Y', '1', '6', ' '), + DPTH16, PSTR2, + PLANE0, OFFS0, SUB4), + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + MAKE_RGB_LE_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, + SUB444), + MAKE_RGB_LE_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, + SUB444), + MAKE_RGB_LE_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, + SUB444), + MAKE_RGB_LE_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, + SUB444), +#else + MAKE_RGB_FORMAT (RGB16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444), + MAKE_RGB_FORMAT (BGR16, "raw video", DPTH565, PSTR222, PLANE0, OFFS0, SUB444), + MAKE_RGB_FORMAT (RGB15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444), + MAKE_RGB_FORMAT (BGR15, "raw video", DPTH555, PSTR222, PLANE0, OFFS0, SUB444), +#endif + + MAKE_YUV_FORMAT (UYVP, "raw video", GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'), + DPTH10_10_10, + PSTR0, PLANE0, OFFS0, SUB422), + MAKE_YUVA_FORMAT (A420, "raw video", GST_MAKE_FOURCC ('A', '4', '2', '0'), + DPTH8888, + PSTR1111, PLANE0123, OFFS0, SUB4204), + MAKE_RGBA_FORMAT (RGB8_PALETTED, "raw video", DPTH8888, PSTR1111, PLANE0, + OFFS0, SUB4444), + MAKE_YUV_FORMAT (YUV9, "raw video", GST_MAKE_FOURCC ('Y', 'U', 'V', '9'), + DPTH888, PSTR111, + PLANE012, OFFS0, SUB410), + MAKE_YUV_FORMAT (YVU9, "raw video", GST_MAKE_FOURCC ('Y', 'V', 'U', '9'), + DPTH888, PSTR111, + PLANE021, OFFS0, SUB410), + MAKE_YUV_FORMAT (IYU1, "raw video", GST_MAKE_FOURCC ('I', 'Y', 'U', '1'), + DPTH888, PSTR0, + PLANE0, OFFS104, SUB411), + MAKE_RGBA_FORMAT (ARGB64, "raw video", DPTH16_16_16_16, PSTR8888, PLANE0, + OFFS2460, + SUB444), + MAKE_YUVA_FORMAT (AYUV64, "raw video", 0x00000000, DPTH16_16_16_16, PSTR8888, + PLANE0, + OFFS2460, SUB444), + MAKE_YUV_FORMAT (r210, "raw video", GST_MAKE_FOURCC ('r', '2', '1', '0'), + DPTH10_10_10, + PSTR444, PLANE0, OFFS0, SUB444), +}; + /** * gst_video_frame_rate: * @pad: pointer to a #GstPad @@ -899,54 +1112,645 @@ gst_video_format_to_fourcc (GstVideoFormat format) { g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); - switch (format) { - case GST_VIDEO_FORMAT_I420: - return GST_MAKE_FOURCC ('I', '4', '2', '0'); - case GST_VIDEO_FORMAT_YV12: - return GST_MAKE_FOURCC ('Y', 'V', '1', '2'); - case GST_VIDEO_FORMAT_YUY2: - return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'); - case GST_VIDEO_FORMAT_YVYU: - return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'); - case GST_VIDEO_FORMAT_UYVY: - return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); - case GST_VIDEO_FORMAT_AYUV: - return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'); - case GST_VIDEO_FORMAT_Y41B: - return GST_MAKE_FOURCC ('Y', '4', '1', 'B'); - case GST_VIDEO_FORMAT_Y42B: - return GST_MAKE_FOURCC ('Y', '4', '2', 'B'); - case GST_VIDEO_FORMAT_Y444: - return GST_MAKE_FOURCC ('Y', '4', '4', '4'); - case GST_VIDEO_FORMAT_v210: - return GST_MAKE_FOURCC ('v', '2', '1', '0'); - case GST_VIDEO_FORMAT_v216: - return GST_MAKE_FOURCC ('v', '2', '1', '6'); - case GST_VIDEO_FORMAT_NV12: - return GST_MAKE_FOURCC ('N', 'V', '1', '2'); - case GST_VIDEO_FORMAT_NV21: - return GST_MAKE_FOURCC ('N', 'V', '2', '1'); - case GST_VIDEO_FORMAT_v308: - return GST_MAKE_FOURCC ('v', '3', '0', '8'); - case GST_VIDEO_FORMAT_Y800: - return GST_MAKE_FOURCC ('Y', '8', '0', '0'); - case GST_VIDEO_FORMAT_Y16: - return GST_MAKE_FOURCC ('Y', '1', '6', ' '); - case GST_VIDEO_FORMAT_UYVP: - return GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'); - case GST_VIDEO_FORMAT_A420: - return GST_MAKE_FOURCC ('A', '4', '2', '0'); - case GST_VIDEO_FORMAT_YUV9: - return GST_MAKE_FOURCC ('Y', 'U', 'V', '9'); - case GST_VIDEO_FORMAT_YVU9: - return GST_MAKE_FOURCC ('Y', 'V', 'U', '9'); - case GST_VIDEO_FORMAT_IYU1: - return GST_MAKE_FOURCC ('I', 'Y', 'U', '1'); - case GST_VIDEO_FORMAT_AYUV64: - return GST_MAKE_FOURCC ('A', 'Y', '6', '4'); - default: - return 0; + if (format >= G_N_ELEMENTS (formats)) + return 0; + + return formats[format].fourcc; +} + +const gchar * +gst_video_format_to_string (GstVideoFormat format) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + + if (format >= G_N_ELEMENTS (formats)) + return NULL; + + return GST_VIDEO_FORMAT_INFO_NAME (&formats[format].info); +} + +/** + * gst_video_format_get_info: + * @format: a #GstVideoFormat + * + * Get the #GstVideoFormatInfo for @format + * + * Returns: The #GstVideoFormatInfo for @format. + */ +const GstVideoFormatInfo * +gst_video_format_get_info (GstVideoFormat format) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + g_return_val_if_fail (format < G_N_ELEMENTS (formats), NULL); + + return &formats[format].info; +} + +/** + * gst_video_info_init: + * @info: a #GstVideoInfo + * + * Initialize @info with default values. + */ +void +gst_video_info_init (GstVideoInfo * info) +{ + g_return_if_fail (info != NULL); + + memset (info, 0, sizeof (GstVideoInfo)); + + info->finfo = &formats[GST_VIDEO_FORMAT_UNKNOWN].info; + + /* arrange for sensible defaults, e.g. if turned into caps */ + info->fps_n = 0; + info->fps_d = 1; + info->par_n = 1; + info->par_d = 1; +} + +/** + * gst_video_info_set_format: + * @info: a #GstVideoInfo + * @format: the format + * @width: a width + * @height: a height + * + * Set the default info for a video frame of @format and @width and @height. + */ +void +gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format, + guint width, guint height) +{ + const GstVideoFormatInfo *finfo; + + g_return_if_fail (info != NULL); + g_return_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN); + + finfo = &formats[format].info; + + info->flags = 0; + info->finfo = finfo; + info->width = width; + info->height = height; + + fill_planes (info); +} + +#if 0 +static const gchar *interlace_mode[] = { + "progressive", + "interleaved", + "mixed", + "fields" +}; + +static const gchar * +gst_interlace_mode_to_string (GstVideoInterlaceMode mode) +{ + if (mode < 0 || mode >= G_N_ELEMENTS (interlace_mode)) + return NULL; + + return interlace_mode[mode]; +} + +static GstVideoInterlaceMode +gst_interlace_mode_from_string (const gchar * mode) +{ + gint i; + for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) { + if (g_str_equal (interlace_mode[i], mode)) + return i; } + return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; +} +#endif + +typedef struct +{ + const gchar *name; + GstVideoChromaSite site; +} ChromaSiteInfo; + +static const ChromaSiteInfo chromasite[] = { + {"jpeg", GST_VIDEO_CHROMA_SITE_JPEG}, + {"mpeg2", GST_VIDEO_CHROMA_SITE_MPEG2}, + {"dv", GST_VIDEO_CHROMA_SITE_DV} +}; + +static GstVideoChromaSite +gst_video_chroma_from_string (const gchar * s) +{ + gint i; + for (i = 0; i < G_N_ELEMENTS (chromasite); i++) { + if (g_str_equal (chromasite[i].name, s)) + return chromasite[i].site; + } + return GST_VIDEO_CHROMA_SITE_UNKNOWN; +} + +static const gchar * +gst_video_chroma_to_string (GstVideoChromaSite site) +{ + gint i; + for (i = 0; i < G_N_ELEMENTS (chromasite); i++) { + if (chromasite[i].site == site) + return chromasite[i].name; + } + return NULL; +} + +typedef struct +{ + const gchar *name; + GstVideoColorimetry color; +} ColorimetryInfo; + +#define MAKE_COLORIMETRY(n,r,m,t,p) { GST_VIDEO_COLORIMETRY_ ##n, \ + { GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \ + GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p } } + +static const ColorimetryInfo colorimetry[] = { + MAKE_COLORIMETRY (BT601, _16_235, BT601, BT709, BT470M), + MAKE_COLORIMETRY (BT709, _16_235, BT709, BT709, BT709), + MAKE_COLORIMETRY (SMPTE240M, _16_235, SMPTE240M, SMPTE240M, SMPTE240M), +}; + +static const ColorimetryInfo * +gst_video_get_colorimetry (const gchar * s) +{ + gint i; + + for (i = 0; i < G_N_ELEMENTS (colorimetry); i++) { + if (g_str_equal (colorimetry[i].name, s)) + return &colorimetry[i]; + } + return NULL; +} + +#define IS_EQUAL(ci,i) (((ci)->color.range == (i)->range) && \ + ((ci)->color.matrix == (i)->matrix) && \ + ((ci)->color.transfer == (i)->transfer) && \ + ((ci)->color.primaries == (i)->primaries)) + + +/** + * gst_video_colorimetry_from_string + * @cinfo: a #GstVideoColorimetry + * @color: a colorimetry string + * + * Parse the colorimetry string and update @cinfo with the parsed + * values. + * + * Returns: #TRUE if @color points to valid colorimetry info. + */ +gboolean +gst_video_colorimetry_from_string (GstVideoColorimetry * cinfo, + const gchar * color) +{ + const ColorimetryInfo *ci; + + if ((ci = gst_video_get_colorimetry (color))) { + *cinfo = ci->color; + } else { + /* FIXME, split and parse */ + cinfo->range = GST_VIDEO_COLOR_RANGE_16_235; + cinfo->matrix = GST_VIDEO_COLOR_MATRIX_BT601; + cinfo->transfer = GST_VIDEO_TRANSFER_BT709; + cinfo->primaries = GST_VIDEO_COLOR_PRIMARIES_BT709; + } + return TRUE; +} + +static void +gst_video_caps_set_colorimetry (GstCaps * caps, GstVideoColorimetry * cinfo) +{ + gint i; + + for (i = 0; i < G_N_ELEMENTS (colorimetry); i++) { + if (IS_EQUAL (&colorimetry[i], cinfo)) { + gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, + colorimetry[i].name, NULL); + return; + } + } + /* FIXME, construct colorimetry */ +} + +/** + * gst_video_colorimetry_matches: + * @cinfo: a #GstVideoInfo + * @color: a colorimetry string + * + * Check if the colorimetry information in @cinfo matches that of the + * string @color. + * + * Returns: #TRUE if @color conveys the same colorimetry info as the color + * information in @info. + */ +gboolean +gst_video_colorimetry_matches (GstVideoColorimetry * cinfo, const gchar * color) +{ + const ColorimetryInfo *ci; + + if ((ci = gst_video_get_colorimetry (color))) + return IS_EQUAL (ci, cinfo); + + return FALSE; +} + +/** + * gst_video_info_from_caps: + * @info: a #GstVideoInfo + * @caps: a #GstCaps + * + * Parse @caps and update @info. + * + * Returns: TRUE if @caps could be parsed + */ +gboolean +gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps) +{ + GstStructure *structure; + const gchar *s; + GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN; + gint width, height; + gint fps_n, fps_d; + gint par_n, par_d; + gboolean interlaced; + + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (caps != NULL, FALSE); + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + + GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps); + + structure = gst_caps_get_structure (caps, 0); + + if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + guint32 fourcc; + + if (!gst_structure_get_fourcc (structure, "format", &fourcc)) + goto no_format; + + format = gst_video_format_from_fourcc (fourcc); + } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) { + int depth; + int bpp; + int endianness = 0; + int red_mask = 0; + int green_mask = 0; + int blue_mask = 0; + int alpha_mask = 0; + + if (!gst_structure_get_int (structure, "depth", &depth) || + !gst_structure_get_int (structure, "bpp", &bpp)) + goto no_bpp_depth; + + if (bpp != 8) { + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get_int (structure, "red_mask", &red_mask); + gst_structure_get_int (structure, "green_mask", &green_mask); + gst_structure_get_int (structure, "blue_mask", &blue_mask); + } + gst_structure_get_int (structure, "alpha_mask", &alpha_mask); + format = gst_video_format_from_masks (depth, bpp, endianness, + red_mask, green_mask, blue_mask, alpha_mask); + } else if (gst_structure_has_name (structure, "video/x-raw-gray")) { + int depth; + int bpp; + int endianness; + + if (!gst_structure_get_int (structure, "depth", &depth) || + !gst_structure_get_int (structure, "bpp", &bpp)) + goto no_bpp_depth; + + /* endianness is mandatory for bpp > 8 */ + if (bpp > 8 && + !gst_structure_get_int (structure, "endianness", &endianness)) + goto no_endianess; + + if (depth == 8 && bpp == 8) { + format = GST_VIDEO_FORMAT_GRAY8; + } else if (depth == 16 && bpp == 16 && endianness == G_BIG_ENDIAN) { + format = GST_VIDEO_FORMAT_GRAY16_BE; + } else if (depth == 16 && bpp == 16 && endianness == G_LITTLE_ENDIAN) { + format = GST_VIDEO_FORMAT_GRAY16_LE; + } + } + + if (format == GST_VIDEO_FORMAT_UNKNOWN) + goto unknown_format; + + if (!gst_structure_get_int (structure, "width", &width)) + goto no_width; + if (!gst_structure_get_int (structure, "height", &height)) + goto no_height; + + gst_video_info_set_format (info, format, width, height); + + if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) { + if (fps_n == 0) { + /* variable framerate */ + info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS; + /* see if we have a max-framerate */ + gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d); + } + info->fps_n = fps_n; + info->fps_d = fps_d; + } else { + /* unspecified is variable framerate */ + info->fps_n = 0; + info->fps_d = 1; + } + + if (gst_structure_get_boolean (structure, "interlaced", &interlaced) + && interlaced) + info->interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED; + else + info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; + + if ((s = gst_structure_get_string (structure, "chroma-site"))) + info->chroma_site = gst_video_chroma_from_string (s); + else + info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN; + + if ((s = gst_structure_get_string (structure, "colorimetry"))) + gst_video_colorimetry_from_string (&info->colorimetry, s); + else + memset (&info->colorimetry, 0, sizeof (GstVideoColorimetry)); + + if (gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_n, &par_d)) { + info->par_n = par_n; + info->par_d = par_d; + } else { + info->par_n = 1; + info->par_d = 1; + } + return TRUE; + + /* ERROR */ +no_format: + { + GST_ERROR ("no format given"); + return FALSE; + } +unknown_format: + { + GST_ERROR ("unknown format"); + return FALSE; + } +no_width: + { + GST_ERROR ("no width property given"); + return FALSE; + } +no_height: + { + GST_ERROR ("no height property given"); + return FALSE; + } + +no_bpp_depth: + { + GST_ERROR ("no bpp or depth given"); + return FALSE; + } + +no_endianess: + { + GST_ERROR ("no endianness given"); + return FALSE; + } +} + +/** + * gst_video_info_to_caps: + * @info: a #GstVideoInfo + * + * Convert the values of @info into a #GstCaps. + * + * Returns: a new #GstCaps containing the info of @info. + */ +GstCaps * +gst_video_info_to_caps (GstVideoInfo * info) +{ + GstCaps *caps; + const gchar *capsname = NULL; + + g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (info->finfo != NULL, NULL); + g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + + if (GST_VIDEO_INFO_IS_YUV (info)) + capsname = "video/x-raw-yuv"; + else if (GST_VIDEO_INFO_IS_RGB (info)) + capsname = "video/x-raw-rgb"; + else if (GST_VIDEO_INFO_IS_GRAY (info)) + capsname = "video/x-raw-gray"; + + caps = gst_caps_new_simple (capsname, + "width", G_TYPE_INT, info->width, + "height", G_TYPE_INT, info->height, + "pixel-aspect-ratio", GST_TYPE_FRACTION, info->par_n, info->par_d, NULL); + + if (GST_VIDEO_INFO_IS_YUV (info)) + gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC, + gst_video_format_to_fourcc (info->finfo->format), NULL); + + gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, + GST_VIDEO_INFO_IS_INTERLACED (info), NULL); + + if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN) + gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING, + gst_video_chroma_to_string (info->chroma_site), NULL); + + gst_video_caps_set_colorimetry (caps, &info->colorimetry); + + if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) { + /* variable fps with a max-framerate */ + gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1, + "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL); + } else { + /* no variable fps or no max-framerate */ + gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, + info->fps_n, info->fps_d, NULL); + } + + return caps; +} + + +static int +fill_planes (GstVideoInfo * info) +{ + gint width, height; + + width = info->width; + height = info->height; + + switch (info->finfo->format) { + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + info->stride[0] = GST_ROUND_UP_4 (width * 2); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_r210: + info->stride[0] = width * 4; + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + info->stride[0] = GST_ROUND_UP_4 (width * 2); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_v308: + info->stride[0] = GST_ROUND_UP_4 (width * 3); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_v210: + info->stride[0] = ((width + 47) / 48) * 128; + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_v216: + info->stride[0] = GST_ROUND_UP_8 (width * 4); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_Y800: + info->stride[0] = GST_ROUND_UP_4 (width); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y16: + info->stride[0] = GST_ROUND_UP_4 (width * 2); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_UYVP: + info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_RGB8_PALETTED: + info->stride[0] = GST_ROUND_UP_4 (width); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_IYU1: + info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + + GST_ROUND_UP_4 (width) / 2); + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + info->stride[0] = width * 8; + info->offset[0] = 0; + info->size = info->stride[0] * height; + break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: /* same as I420, but plane 1+2 swapped */ + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2); + info->stride[2] = info->stride[1]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height); + info->offset[2] = info->offset[1] + + info->stride[1] * (GST_ROUND_UP_2 (height) / 2); + info->size = info->offset[2] + + info->stride[2] * (GST_ROUND_UP_2 (height) / 2); + break; + case GST_VIDEO_FORMAT_Y41B: + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = GST_ROUND_UP_16 (width) / 4; + info->stride[2] = info->stride[1]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * height; + info->offset[2] = info->offset[1] + info->stride[1] * height; + /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */ + info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height; + break; + case GST_VIDEO_FORMAT_Y42B: + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = GST_ROUND_UP_8 (width) / 2; + info->stride[2] = info->stride[1]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * height; + info->offset[2] = info->offset[1] + info->stride[1] * height; + /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */ + info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height; + break; + case GST_VIDEO_FORMAT_Y444: + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = info->stride[0]; + info->stride[2] = info->stride[0]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * height; + info->offset[2] = info->offset[1] * 2; + info->size = info->stride[0] * height * 3; + break; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = info->stride[0]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height); + info->size = info->stride[0] * GST_ROUND_UP_2 (height) * 3 / 2; + break; + case GST_VIDEO_FORMAT_A420: + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2); + info->stride[2] = info->stride[1]; + info->stride[3] = info->stride[0]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height); + info->offset[2] = info->offset[1] + + info->stride[1] * (GST_ROUND_UP_2 (height) / 2); + info->offset[3] = info->offset[2] + + info->stride[2] * (GST_ROUND_UP_2 (height) / 2); + info->size = info->offset[3] + info->stride[0]; + break; + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + info->stride[0] = GST_ROUND_UP_4 (width); + info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4); + info->stride[2] = info->stride[1]; + info->offset[0] = 0; + info->offset[1] = info->stride[0] * height; + info->offset[2] = info->offset[1] + + info->stride[1] * (GST_ROUND_UP_4 (height) / 4); + info->size = info->offset[2] + + info->stride[2] * (GST_ROUND_UP_4 (height) / 4); + break; + case GST_VIDEO_FORMAT_UNKNOWN: + GST_ERROR ("invalid format"); + g_warning ("invalid format"); + break; + } + return 0; } /* @@ -1049,6 +1853,72 @@ gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask) return GST_VIDEO_FORMAT_UNKNOWN; } +/** + * gst_video_format_from_masks: + * @depth: the amount of bits used for a pixel + * @bpp: the amount of bits used to store a pixel. This value is bigger than + * @depth + * @endianness: the endianness of the masks + * @red_mask: the red mask + * @green_mask: the green mask + * @blue_mask: the blue mask + * @alpha_mask: the optional alpha mask + * + * Find the #GstVideoFormat for the given parameters. + * + * Returns: a #GstVideoFormat or GST_VIDEO_FORMAT_UNKNOWN when the parameters to + * not specify a known format. + */ +GstVideoFormat +gst_video_format_from_masks (gint depth, gint bpp, gint endianness, + gint red_mask, gint green_mask, gint blue_mask, gint alpha_mask) +{ + GstVideoFormat format; + + /* our caps system handles 24/32bpp RGB as big-endian. */ + if ((bpp == 24 || bpp == 32) && endianness == G_LITTLE_ENDIAN) { + red_mask = GUINT32_TO_BE (red_mask); + green_mask = GUINT32_TO_BE (green_mask); + blue_mask = GUINT32_TO_BE (blue_mask); + endianness = G_BIG_ENDIAN; + if (bpp == 24) { + red_mask >>= 8; + green_mask >>= 8; + blue_mask >>= 8; + } + } + + if (depth == 30 && bpp == 32) { + format = GST_VIDEO_FORMAT_r210; + } else if (depth == 24 && bpp == 32) { + format = gst_video_format_from_rgb32_masks (red_mask, green_mask, + blue_mask); + } else if (depth == 32 && bpp == 32 && alpha_mask) { + format = gst_video_format_from_rgba32_masks (red_mask, green_mask, + blue_mask, alpha_mask); + } else if (depth == 24 && bpp == 24) { + format = gst_video_format_from_rgb24_masks (red_mask, green_mask, + blue_mask); + } else if ((depth == 15 || depth == 16) && bpp == 16 && + endianness == G_BYTE_ORDER) { + format = gst_video_format_from_rgb16_masks (red_mask, green_mask, + blue_mask); + } else if (depth == 8 && bpp == 8) { + format = GST_VIDEO_FORMAT_RGB8_PALETTED; + } else if (depth == 64 && bpp == 64) { + format = gst_video_format_from_rgba32_masks (red_mask, green_mask, + blue_mask, alpha_mask); + if (format == GST_VIDEO_FORMAT_ARGB) { + format = GST_VIDEO_FORMAT_ARGB64; + } else { + format = GST_VIDEO_FORMAT_UNKNOWN; + } + } else { + format = GST_VIDEO_FORMAT_UNKNOWN; + } + return format; +} + /** * gst_video_format_is_rgb: * @format: a #GstVideoFormat @@ -1057,54 +1927,19 @@ gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask) * * Since: 0.10.16 * + * Deprecated: Use #GstVideoFormatInfo and #GST_VIDEO_FORMAT_INFO_IS_RGB + * * Returns: TRUE if @format represents RGB video */ gboolean gst_video_format_is_rgb (GstVideoFormat format) { - switch (format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_Y41B: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_v210: - case GST_VIDEO_FORMAT_v216: - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_v308: - case GST_VIDEO_FORMAT_UYVP: - case GST_VIDEO_FORMAT_A420: - case GST_VIDEO_FORMAT_YUV9: - case GST_VIDEO_FORMAT_YVU9: - case GST_VIDEO_FORMAT_IYU1: - case GST_VIDEO_FORMAT_AYUV64: - return FALSE; - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_RGB16: - case GST_VIDEO_FORMAT_BGR16: - case GST_VIDEO_FORMAT_RGB15: - case GST_VIDEO_FORMAT_BGR15: - case GST_VIDEO_FORMAT_RGB8_PALETTED: - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_r210: - return TRUE; - default: - return FALSE; - } + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + + if (format >= G_N_ELEMENTS (formats)) + return FALSE; + + return GST_VIDEO_FORMAT_INFO_IS_RGB (&formats[format].info); } /** @@ -1115,56 +1950,19 @@ gst_video_format_is_rgb (GstVideoFormat format) * * Since: 0.10.16 * + * Deprecated: Use #GstVideoFormatInfo and #GST_VIDEO_FORMAT_INFO_IS_YUV + * * Returns: TRUE if @format represents YUV video */ gboolean gst_video_format_is_yuv (GstVideoFormat format) { - switch (format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_Y41B: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_v210: - case GST_VIDEO_FORMAT_v216: - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_v308: - case GST_VIDEO_FORMAT_Y800: - case GST_VIDEO_FORMAT_Y16: - case GST_VIDEO_FORMAT_UYVP: - case GST_VIDEO_FORMAT_A420: - case GST_VIDEO_FORMAT_YUV9: - case GST_VIDEO_FORMAT_YVU9: - case GST_VIDEO_FORMAT_IYU1: - case GST_VIDEO_FORMAT_AYUV64: - return TRUE; - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_RGB16: - case GST_VIDEO_FORMAT_BGR16: - case GST_VIDEO_FORMAT_RGB15: - case GST_VIDEO_FORMAT_BGR15: - case GST_VIDEO_FORMAT_RGB8_PALETTED: - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_r210: - return FALSE; - default: - return FALSE; - } + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + + if (format >= G_N_ELEMENTS (formats)) + return FALSE; + + return GST_VIDEO_FORMAT_INFO_IS_YUV (&formats[format].info); } /** @@ -1175,21 +1973,19 @@ gst_video_format_is_yuv (GstVideoFormat format) * * Since: 0.10.29 * + * Deprecated: Use #GstVideoFormatInfo and #GST_VIDEO_FORMAT_INFO_IS_GRAY + * * Returns: TRUE if @format represents grayscale video */ gboolean gst_video_format_is_gray (GstVideoFormat format) { - switch (format) { - case GST_VIDEO_FORMAT_GRAY8: - case GST_VIDEO_FORMAT_GRAY16_BE: - case GST_VIDEO_FORMAT_GRAY16_LE: - case GST_VIDEO_FORMAT_Y800: - case GST_VIDEO_FORMAT_Y16: - return TRUE; - default: - return FALSE; - } + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + + if (format >= G_N_ELEMENTS (formats)) + return FALSE; + + return GST_VIDEO_FORMAT_INFO_IS_GRAY (&formats[format].info); } /** @@ -1201,57 +1997,19 @@ gst_video_format_is_gray (GstVideoFormat format) * * Since: 0.10.16 * + * Deprecated: Use #GstVideoFormatInfo and #GST_VIDEO_FORMAT_INFO_HAS_ALPHA + * * Returns: TRUE if @format has an alpha channel */ gboolean gst_video_format_has_alpha (GstVideoFormat format) { - switch (format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - case GST_VIDEO_FORMAT_Y41B: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_v210: - case GST_VIDEO_FORMAT_v216: - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_v308: - case GST_VIDEO_FORMAT_Y800: - case GST_VIDEO_FORMAT_Y16: - case GST_VIDEO_FORMAT_UYVP: - case GST_VIDEO_FORMAT_YUV9: - case GST_VIDEO_FORMAT_YVU9: - case GST_VIDEO_FORMAT_IYU1: - return FALSE; - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_A420: - case GST_VIDEO_FORMAT_RGB8_PALETTED: - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_AYUV64: - return TRUE; - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_RGB16: - case GST_VIDEO_FORMAT_BGR16: - case GST_VIDEO_FORMAT_RGB15: - case GST_VIDEO_FORMAT_BGR15: - case GST_VIDEO_FORMAT_r210: - return FALSE; - default: - return FALSE; - } + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + + if (format >= G_N_ELEMENTS (formats)) + return FALSE; + + return GST_VIDEO_FORMAT_INFO_HAS_ALPHA (&formats[format].info); } /** @@ -1270,59 +2028,12 @@ gst_video_format_has_alpha (GstVideoFormat format) int gst_video_format_get_component_depth (GstVideoFormat format, int component) { - if (component == 3 && !gst_video_format_has_alpha (format)) + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + + if (format >= G_N_ELEMENTS (formats)) return 0; - switch (format) { - case GST_VIDEO_FORMAT_RGB16: - case GST_VIDEO_FORMAT_BGR16: - if (component == 1) - return 6; - return 5; - case GST_VIDEO_FORMAT_RGB15: - case GST_VIDEO_FORMAT_BGR15: - return 5; - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - case GST_VIDEO_FORMAT_Y41B: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - case GST_VIDEO_FORMAT_v308: - case GST_VIDEO_FORMAT_Y800: - case GST_VIDEO_FORMAT_YUV9: - case GST_VIDEO_FORMAT_YVU9: - case GST_VIDEO_FORMAT_IYU1: - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_A420: - case GST_VIDEO_FORMAT_RGB8_PALETTED: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - default: - return 8; - case GST_VIDEO_FORMAT_v210: - case GST_VIDEO_FORMAT_UYVP: - case GST_VIDEO_FORMAT_r210: - return 10; - case GST_VIDEO_FORMAT_Y16: - case GST_VIDEO_FORMAT_v216: - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_AYUV64: - return 16; - } - + return GST_VIDEO_FORMAT_INFO_DEPTH (&formats[format].info, component); } /** @@ -1459,82 +2170,10 @@ gst_video_format_get_pixel_stride (GstVideoFormat format, int component) g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); g_return_val_if_fail (component >= 0 && component <= 3, 0); - switch (format) { - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_Y41B: - case GST_VIDEO_FORMAT_Y42B: - case GST_VIDEO_FORMAT_Y444: - case GST_VIDEO_FORMAT_A420: - case GST_VIDEO_FORMAT_YUV9: - case GST_VIDEO_FORMAT_YVU9: - return 1; - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_YVYU: - case GST_VIDEO_FORMAT_UYVY: - if (component == 0) { - return 2; - } else { - return 4; - } - case GST_VIDEO_FORMAT_IYU1: - /* doesn't make much sense for IYU1 because it's 1 or 3 - * for luma depending on position */ - return 0; - case GST_VIDEO_FORMAT_AYUV: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - case GST_VIDEO_FORMAT_r210: - return 4; - case GST_VIDEO_FORMAT_RGB16: - case GST_VIDEO_FORMAT_BGR16: - case GST_VIDEO_FORMAT_RGB15: - case GST_VIDEO_FORMAT_BGR15: - return 2; - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_v308: - return 3; - case GST_VIDEO_FORMAT_v210: - /* v210 is packed at the bit level, so pixel stride doesn't make sense */ - return 0; - case GST_VIDEO_FORMAT_v216: - if (component == 0) { - return 4; - } else { - return 8; - } - case GST_VIDEO_FORMAT_NV12: - case GST_VIDEO_FORMAT_NV21: - if (component == 0) { - return 1; - } else { - return 2; - } - case GST_VIDEO_FORMAT_GRAY8: - case GST_VIDEO_FORMAT_Y800: - return 1; - case GST_VIDEO_FORMAT_GRAY16_BE: - case GST_VIDEO_FORMAT_GRAY16_LE: - case GST_VIDEO_FORMAT_Y16: - return 2; - case GST_VIDEO_FORMAT_UYVP: - /* UYVP is packed at the bit level, so pixel stride doesn't make sense */ - return 0; - case GST_VIDEO_FORMAT_RGB8_PALETTED: - return 1; - case GST_VIDEO_FORMAT_ARGB64: - case GST_VIDEO_FORMAT_AYUV64: - return 8; - default: - return 0; - } + if (format >= G_N_ELEMENTS (formats)) + return 0; + + return GST_VIDEO_FORMAT_INFO_PSTRIDE (&formats[format].info, component); } /** @@ -1972,7 +2611,8 @@ gst_video_format_get_component_offset (GstVideoFormat format, default: break; } - GST_WARNING ("unhandled format %d or component %d", format, component); + GST_WARNING ("unhandled format %s or component %d", + gst_video_format_to_string (format), component); return 0; } diff --git a/gst-libs/gst/video/video.h b/gst-libs/gst/video/video.h index 36750e9727..d1a19322d0 100644 --- a/gst-libs/gst/video/video.h +++ b/gst-libs/gst/video/video.h @@ -435,6 +435,467 @@ typedef enum { */ #define GST_VIDEO_BUFFER_PROGRESSIVE GST_BUFFER_FLAG_MEDIA4 +/* Backported from 0.11 */ + +#define GST_VIDEO_MAX_PLANES 4 +#define GST_VIDEO_MAX_COMPONENTS 4 + +typedef struct _GstVideoFormatInfo GstVideoFormatInfo; + +/** + * GstVideoFormatFlags: + * @GST_VIDEO_FORMAT_FLAG_YUV: The video format is YUV, components are numbered + * 0=Y, 1=U, 2=V. + * @GST_VIDEO_FORMAT_FLAG_RGB: The video format is RGB, components are numbered + * 0=R, 1=G, 2=B. + * @GST_VIDEO_FORMAT_FLAG_GRAY: The video is gray, there is one gray component + * with index 0. + * @GST_VIDEO_FORMAT_FLAG_ALPHA: The video format has an alpha components with + * the number 3. + * @GST_VIDEO_FORMAT_FLAG_LE: The video format has data stored in little + * endianness. + * @GST_VIDEO_FORMAT_FLAG_PALETTE: The video format has a palette. + * @GST_VIDEO_FORMAT_FLAG_COMPLEX: The video format has a complex layout that + * can't be described with the usual information in the #GstVideoFormatInfo. + * + * The different video flags that a format info can have. + */ +typedef enum +{ + GST_VIDEO_FORMAT_FLAG_YUV = (1 << 0), + GST_VIDEO_FORMAT_FLAG_RGB = (1 << 1), + GST_VIDEO_FORMAT_FLAG_GRAY = (1 << 2), + GST_VIDEO_FORMAT_FLAG_ALPHA = (1 << 3), + GST_VIDEO_FORMAT_FLAG_LE = (1 << 4), + GST_VIDEO_FORMAT_FLAG_PALETTE = (1 << 5), + GST_VIDEO_FORMAT_FLAG_COMPLEX = (1 << 6) +} GstVideoFormatFlags; + +#define GST_VIDEO_COMP_Y 0 +#define GST_VIDEO_COMP_U 1 +#define GST_VIDEO_COMP_V 2 + +#define GST_VIDEO_COMP_R 0 +#define GST_VIDEO_COMP_G 1 +#define GST_VIDEO_COMP_B 2 + +#define GST_VIDEO_COMP_A 3 + +/** + * GstVideoFormatUnpack: + * @info: a #GstVideoFormatInfo + * @dest: a destination array + * @data: pointers to the data planes + * @stride: strides of the planes + * @x: the x position in the image to start from + * @y: the y position in the image to start from + * @width: the amount of pixels to unpack. + * + * Unpacks @width pixels from the given planes and strides containing data of + * format @info. The pixels will be unpacked into @dest which each component + * interleaved. @dest should at least be big enough to hold @width * + * n_components * size(unpack_format) bytes. + */ +typedef void (*GstVideoFormatUnpack) (GstVideoFormatInfo *info, gpointer dest, + const gpointer data[GST_VIDEO_MAX_PLANES], + const gint stride[GST_VIDEO_MAX_PLANES], + gint x, gint y, gint width); +/** + * GstVideoFormatPack: + * @info: a #GstVideoFormatInfo + * @src: a source array + * @data: pointers to the destination data planes + * @stride: strides of the destination planes + * @x: the x position in the image to pack to + * @y: the y position in the image to pack to + * @width: the amount of pixels to pack. + * + * Packs @width pixels from @src to the given planes and strides in the + * format @info. The pixels from source have each component interleaved + * and will be packed into the planes in @data. + */ +typedef void (*GstVideoFormatPack) (GstVideoFormatInfo *info, const gpointer src, + gpointer data[GST_VIDEO_MAX_PLANES], + const gint stride[GST_VIDEO_MAX_PLANES], + gint x, gint y, gint width); + +/** + * GstVideoFormatInfo: + * @format: #GstVideoFormat + * @name: string representation of the format + * @description: use readable description of the format + * @flags: #GstVideoFormatFlags + * @bits: The number of bits used to pack data items. This can be less than 8 + * when multiple pixels are stored in a byte. for values > 8 multiple bytes + * should be read according to the endianness flag before applying the shift + * and mask. + * @n_components: the number of components in the video format. + * @shift: the number of bits to shift away to get the component data + * @depth: the depth in bits for each component + * @pixel_stride: the pixel stride of each component. This is the amount of + * bytes to the pixel immediately to the right. When bits < 8, the stride is + * expressed in bits. + * @n_planes: the number of planes for this format. The number of planes can be + * less than the amount of components when multiple components are packed into + * one plane. + * @plane: the plane number where a component can be found + * @poffset: the offset in the plane where the first pixel of the components + * can be found. If bits < 8 the amount is specified in bits. + * @w_sub: subsampling factor of the width for the component. Use + * GST_VIDEO_SUB_SCALE to scale a width. + * @h_sub: subsampling factor of the height for the component. Use + * GST_VIDEO_SUB_SCALE to scale a height. + * @unpack_format: the format of the unpacked pixels. + * @unpack_func: an unpack function for this format + * @pack_func: an pack function for this format + * + * Information for a video format. + */ +struct _GstVideoFormatInfo { + GstVideoFormat format; + const gchar *name; + const gchar *description; + GstVideoFormatFlags flags; + guint bits; + guint n_components; + guint shift[GST_VIDEO_MAX_COMPONENTS]; + guint depth[GST_VIDEO_MAX_COMPONENTS]; + gint pixel_stride[GST_VIDEO_MAX_COMPONENTS]; + guint n_planes; + guint plane[GST_VIDEO_MAX_COMPONENTS]; + guint poffset[GST_VIDEO_MAX_COMPONENTS]; + guint w_sub[GST_VIDEO_MAX_COMPONENTS]; + guint h_sub[GST_VIDEO_MAX_COMPONENTS]; + + GstVideoFormat unpack_format; + GstVideoFormatUnpack unpack_func; + GstVideoFormatPack pack_func; +}; + +#define GST_VIDEO_FORMAT_INFO_FORMAT(info) ((info)->format) +#define GST_VIDEO_FORMAT_INFO_NAME(info) ((info)->name) +#define GST_VIDEO_FORMAT_INFO_FLAGS(info) ((info)->flags) + +#define GST_VIDEO_FORMAT_INFO_IS_YUV(info) ((info)->flags & GST_VIDEO_FORMAT_FLAG_YUV) +#define GST_VIDEO_FORMAT_INFO_IS_RGB(info) ((info)->flags & GST_VIDEO_FORMAT_FLAG_RGB) +#define GST_VIDEO_FORMAT_INFO_IS_GRAY(info) ((info)->flags & GST_VIDEO_FORMAT_FLAG_GRAY) +#define GST_VIDEO_FORMAT_INFO_HAS_ALPHA(info) ((info)->flags & GST_VIDEO_FORMAT_FLAG_ALPHA) +#define GST_VIDEO_FORMAT_INFO_IS_LE(info) ((info)->flags & GST_VIDEO_FORMAT_FLAG_LE) +#define GST_VIDEO_FORMAT_INFO_HAS_PALETTE(info) ((info)->flags & GST_VIDEO_FORMAT_FLAG_PALETTE) + +#define GST_VIDEO_FORMAT_INFO_BITS(info) ((info)->bits) +#define GST_VIDEO_FORMAT_INFO_N_COMPONENTS(info) ((info)->n_components) +#define GST_VIDEO_FORMAT_INFO_SHIFT(info,c) ((info)->shift[c]) +#define GST_VIDEO_FORMAT_INFO_DEPTH(info,c) ((info)->depth[c]) +#define GST_VIDEO_FORMAT_INFO_PSTRIDE(info,c) ((info)->pixel_stride[c]) +#define GST_VIDEO_FORMAT_INFO_N_PLANES(info) ((info)->n_planes) +#define GST_VIDEO_FORMAT_INFO_PLANE(info,c) ((info)->plane[c]) +#define GST_VIDEO_FORMAT_INFO_POFFSET(info,c) ((info)->poffset[c]) +#define GST_VIDEO_FORMAT_INFO_W_SUB(info,c) ((info)->w_sub[c]) +#define GST_VIDEO_FORMAT_INFO_H_SUB(info,c) ((info)->h_sub[c]) + +#define GST_VIDEO_SUB_SCALE(scale,val) (-((-((gint)val))>>(scale))) + +#define GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(info,c,w) GST_VIDEO_SUB_SCALE ((info)->w_sub[(c)],(w)) +#define GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info,c,h) GST_VIDEO_SUB_SCALE ((info)->h_sub[(c)],(h)) + +#define GST_VIDEO_FORMAT_INFO_DATA(info,planes,comp) \ + (((guint8*)(planes)[info->plane[comp]]) + info->poffset[comp]) +#define GST_VIDEO_FORMAT_INFO_STRIDE(info,strides,comp) ((strides)[info->plane[comp]]) +#define GST_VIDEO_FORMAT_INFO_OFFSET(info,offsets,comp) \ + (((offsets)[info->plane[comp]]) + info->poffset[comp]) + +typedef struct _GstVideoInfo GstVideoInfo; + +const GstVideoFormatInfo * + gst_video_format_get_info (GstVideoFormat format) G_GNUC_CONST; +/** + * GstVideoInterlaceMode: + * @GST_VIDEO_INTERLACE_MODE_PROGRESSIVE: all frames are progressive + * @GST_VIDEO_INTERLACE_MODE_INTERLEAVED: video is interlaced and all fields + * are interlaced in one frame. + * @GST_VIDEO_INTERLACE_MODE_MIXED: video contains both interlaced and + * progressive frames, the buffer flags describe the frame and fields. + * @GST_VIDEO_INTERLACE_MODE_FIELDS: video is interlaced and fields are stored + * separately. Use the id property to get access to the required field. + * + * The possible values of the #GstVideoInterlaceMode describing the interlace + * mode of the stream. + */ +typedef enum { + GST_VIDEO_INTERLACE_MODE_PROGRESSIVE = 0, + GST_VIDEO_INTERLACE_MODE_INTERLEAVED, + GST_VIDEO_INTERLACE_MODE_MIXED, + GST_VIDEO_INTERLACE_MODE_FIELDS +} GstVideoInterlaceMode; + +/** + * GstVideoFlags: + * @GST_VIDEO_FLAG_NONE: no flags + * @GST_VIDEO_FLAG_VARIABLE_FPS: a variable fps is selected, fps_n and fps_d + * denote the maximum fps of the video + * + * Extra video flags + */ +typedef enum { + GST_VIDEO_FLAG_NONE = 0, + GST_VIDEO_FLAG_VARIABLE_FPS = (1 << 1) +} GstVideoFlags; + +/** + * GstVideoChroma: + * @GST_VIDEO_CHROMA_SITE_UNKNOWN: unknown cositing + * @GST_VIDEO_CHROMA_SITE_NONE: no cositing + * @GST_VIDEO_CHROMA_SITE_H_COSITED: chroma is horizontally cosited + * @GST_VIDEO_CHROMA_SITE_V_COSITED: chroma is vertically cosited + * @GST_VIDEO_CHROMA_SITE_ALT_LINE: choma samples are sited on alternate lines + * @GST_VIDEO_CHROMA_SITE_COSITED: chroma samples cosited with luma samples + * @GST_VIDEO_CHROMA_SITE_JPEG: jpeg style cositing, also for mpeg1 and mjpeg + * @GST_VIDEO_CHROMA_SITE_MPEG2: mpeg2 style cositing + * @GST_VIDEO_CHROMA_SITE_DV: DV style cositing + * + * Various Chroma sitings. + */ +typedef enum { + GST_VIDEO_CHROMA_SITE_UNKNOWN = 0, + GST_VIDEO_CHROMA_SITE_NONE = (1 << 0), + GST_VIDEO_CHROMA_SITE_H_COSITED = (1 << 1), + GST_VIDEO_CHROMA_SITE_V_COSITED = (1 << 2), + GST_VIDEO_CHROMA_SITE_ALT_LINE = (1 << 3), + /* some common chroma cositing */ + GST_VIDEO_CHROMA_SITE_COSITED = (GST_VIDEO_CHROMA_SITE_H_COSITED | GST_VIDEO_CHROMA_SITE_V_COSITED), + GST_VIDEO_CHROMA_SITE_JPEG = (GST_VIDEO_CHROMA_SITE_NONE), + GST_VIDEO_CHROMA_SITE_MPEG2 = (GST_VIDEO_CHROMA_SITE_H_COSITED), + GST_VIDEO_CHROMA_SITE_DV = (GST_VIDEO_CHROMA_SITE_COSITED | GST_VIDEO_CHROMA_SITE_ALT_LINE), +} GstVideoChromaSite; + + +/** + * GstVideoColorRange: + * @GST_VIDEO_COLOR_RANGE_UNKNOWN: unknown range + * @GST_VIDEO_COLOR_RANGE_0_255: [0..255] for 8 bit components + * @GST_VIDEO_COLOR_RANGE_16_235: [16..235] for 8 bit components. Chroma has + * [16..240] range. + * + * Possible color range values. These constants are defined for 8 bit color + * values and can be scaled for other bit depths. + */ +typedef enum { + GST_VIDEO_COLOR_RANGE_UNKNOWN = 0, + GST_VIDEO_COLOR_RANGE_0_255, + GST_VIDEO_COLOR_RANGE_16_235 +} GstVideoColorRange; + +/** + * GstVideoColorMatrix: + * @GST_VIDEO_COLOR_MATRIX_UNKNOWN: unknown matrix + * @GST_VIDEO_COLOR_MATRIX_RGB: identity matrix + * @GST_VIDEO_COLOR_MATRIX_FCC: FCC color matrix + * @GST_VIDEO_COLOR_MATRIX_BT709: ITU-R BT.709 color matrix + * @GST_VIDEO_COLOR_MATRIX_BT601: ITU-R BT.601 color matrix + * @GST_VIDEO_COLOR_MATRIX_SMPTE240M: SMPTE 240M color matrix + * + * The color matrix is used to convert between Y'PbPr and + * non-linear RGB (R'G'B') + */ +typedef enum { + GST_VIDEO_COLOR_MATRIX_UNKNOWN = 0, + GST_VIDEO_COLOR_MATRIX_RGB, + GST_VIDEO_COLOR_MATRIX_FCC, + GST_VIDEO_COLOR_MATRIX_BT709, + GST_VIDEO_COLOR_MATRIX_BT601, + GST_VIDEO_COLOR_MATRIX_SMPTE240M +} GstVideoColorMatrix; + +/** + * GstVideoTransferFunction: + * @GST_VIDEO_TRANSFER_UNKNOWN: unknown transfer function + * @GST_VIDEO_TRANSFER_GAMMA10: linear RGB, gamma 1.0 curve + * @GST_VIDEO_TRANSFER_GAMMA18: Gamma 1.8 curve + * @GST_VIDEO_TRANSFER_GAMMA20: Gamma 2.0 curve + * @GST_VIDEO_TRANSFER_GAMMA22: Gamma 2.2 curve + * @GST_VIDEO_TRANSFER_BT709: Gamma 2.2 curve with a linear segment in the lower + * range + * @GST_VIDEO_TRANSFER_SMPTE240M: Gamma 2.2 curve with a linear segment in the + * lower range + * @GST_VIDEO_TRANSFER_SRGB: Gamma 2.4 curve with a linear segment in the lower + * range + * @GST_VIDEO_TRANSFER_GAMMA28: Gamma 2.8 curve + * @GST_VIDEO_TRANSFER_LOG100: Logarithmic transfer characteristic + * 100:1 range + * @GST_VIDEO_TRANSFER_LOG316: Logarithmic transfer characteristic + * 316.22777:1 range + * + * The video transfer function defines the formula for converting between + * non-linear RGB (R'G'B') and linear RGB + */ +typedef enum { + GST_VIDEO_TRANSFER_UNKNOWN = 0, + GST_VIDEO_TRANSFER_GAMMA10, + GST_VIDEO_TRANSFER_GAMMA18, + GST_VIDEO_TRANSFER_GAMMA20, + GST_VIDEO_TRANSFER_GAMMA22, + GST_VIDEO_TRANSFER_BT709, + GST_VIDEO_TRANSFER_SMPTE240M, + GST_VIDEO_TRANSFER_SRGB, + GST_VIDEO_TRANSFER_GAMMA28, + GST_VIDEO_TRANSFER_LOG100, + GST_VIDEO_TRANSFER_LOG316 +} GstVideoTransferFunction; + +/** + * GstVideoColorPrimaries: + * @GST_VIDEO_COLOR_PRIMARIES_UNKNOWN: unknown color primaries + * @GST_VIDEO_COLOR_PRIMARIES_BT709: BT709 primaries + * @GST_VIDEO_COLOR_PRIMARIES_BT470M: BT470M primaries + * @GST_VIDEO_COLOR_PRIMARIES_BT470BG: BT470BG primaries + * @GST_VIDEO_COLOR_PRIMARIES_SMPTE170M: SMPTE170M primaries + * @GST_VIDEO_COLOR_PRIMARIES_SMPTE240M: SMPTE240M primaries + * + * The color primaries define the how to transform linear RGB values to and from + * the CIE XYZ colorspace. + */ +typedef enum { + GST_VIDEO_COLOR_PRIMARIES_UNKNOWN = 0, + GST_VIDEO_COLOR_PRIMARIES_BT709, + GST_VIDEO_COLOR_PRIMARIES_BT470M, + GST_VIDEO_COLOR_PRIMARIES_BT470BG, + GST_VIDEO_COLOR_PRIMARIES_SMPTE170M, + GST_VIDEO_COLOR_PRIMARIES_SMPTE240M +} GstVideoColorPrimaries; + +/** + * GstVideoColorimetry: + * @range: the color range. This is the valid range for the samples. + * It is used to convert the samples to Y'PbPr values. + * @matrix: the color matrix. Used to convert between Y'PbPr and + * non-linear RGB (R'G'B') + * @transfer: the transfer function. used to convert between R'G'B' and RGB + * @primaries: color primaries. used to convert between R'G'B' and CIE XYZ + * + * Structure describing the color info. + */ +typedef struct { + GstVideoColorRange range; + GstVideoColorMatrix matrix; + GstVideoTransferFunction transfer; + GstVideoColorPrimaries primaries; +} GstVideoColorimetry; + +/* predefined colorimetry */ +#define GST_VIDEO_COLORIMETRY_BT601 "bt601" +#define GST_VIDEO_COLORIMETRY_BT709 "bt709" +#define GST_VIDEO_COLORIMETRY_SMPTE240M "smpte240m" + +gboolean gst_video_colorimetry_matches (GstVideoColorimetry *cinfo, const gchar *color); +gboolean gst_video_colorimetry_from_string (GstVideoColorimetry *cinfo, const gchar *color); +gchar * gst_video_colorimetry_to_string (GstVideoColorimetry *cinfo); + +/** + * GstVideoInfo: + * @finfo: the format info of the video + * @interlace_mode: the interlace mode + * @flags: additional video flags + * @width: the width of the video + * @height: the height of the video + * @size: the default size of one frame + * @chroma_site: a #GstVideoChromaSite. + * @colorimetry: the colorimetry info + * @palette: a buffer with palette data + * @par_n: the pixel-aspect-ratio numerator + * @par_d: the pixel-aspect-ratio demnominator + * @fps_n: the framerate numerator + * @fps_d: the framerate demnominator + * @offset: offsets of the planes + * @stride: strides of the planes + * + * Information describing image properties. This information can be filled + * in from GstCaps with gst_video_info_from_caps(). The information is also used + * to store the specific video info when mapping a video frame with + * gst_video_frame_map(). + * + * Use the provided macros to access the info in this structure. + */ +struct _GstVideoInfo { + const GstVideoFormatInfo *finfo; + + GstVideoInterlaceMode interlace_mode; + GstVideoFlags flags; + gint width; + gint height; + gsize size; + + GstVideoChromaSite chroma_site; + GstVideoColorimetry colorimetry; + + GstBuffer *palette; + + gint par_n; + gint par_d; + gint fps_n; + gint fps_d; + + gsize offset[GST_VIDEO_MAX_PLANES]; + gint stride[GST_VIDEO_MAX_PLANES]; +}; + +/* general info */ +#define GST_VIDEO_INFO_FORMAT(i) (GST_VIDEO_FORMAT_INFO_FORMAT((i)->finfo)) +#define GST_VIDEO_INFO_NAME(i) (GST_VIDEO_FORMAT_INFO_NAME((i)->finfo)) +#define GST_VIDEO_INFO_IS_YUV(i) (GST_VIDEO_FORMAT_INFO_IS_YUV((i)->finfo)) +#define GST_VIDEO_INFO_IS_RGB(i) (GST_VIDEO_FORMAT_INFO_IS_RGB((i)->finfo)) +#define GST_VIDEO_INFO_IS_GRAY(i) (GST_VIDEO_FORMAT_INFO_IS_GRAY((i)->finfo)) +#define GST_VIDEO_INFO_HAS_ALPHA(i) (GST_VIDEO_FORMAT_INFO_HAS_ALPHA((i)->finfo)) + +#define GST_VIDEO_INFO_INTERLACE_MODE(i) ((i)->interlace_mode) +#define GST_VIDEO_INFO_IS_INTERLACED(i) ((i)->interlace_mode != GST_VIDEO_INTERLACE_MODE_PROGRESSIVE) +#define GST_VIDEO_INFO_FLAGS(i) ((i)->flags) +#define GST_VIDEO_INFO_WIDTH(i) ((i)->width) +#define GST_VIDEO_INFO_HEIGHT(i) ((i)->height) +#define GST_VIDEO_INFO_SIZE(i) ((i)->size) +#define GST_VIDEO_INFO_PAR_N(i) ((i)->par_n) +#define GST_VIDEO_INFO_PAR_D(i) ((i)->par_d) +#define GST_VIDEO_INFO_FPS_N(i) ((i)->fps_n) +#define GST_VIDEO_INFO_FPS_D(i) ((i)->fps_d) + +/* dealing with GstVideoInfo flags */ +#define GST_VIDEO_INFO_FLAG_IS_SET(i,flag) ((GST_VIDEO_INFO_FLAGS(i) & (flag)) == (flag)) +#define GST_VIDEO_INFO_FLAG_SET(i,flag) (GST_VIDEO_INFO_FLAGS(i) |= (flag)) +#define GST_VIDEO_INFO_FLAG_UNSET(i,flag) (GST_VIDEO_INFO_FLAGS(i) &= ~(flag)) + +/* dealing with planes */ +#define GST_VIDEO_INFO_N_PLANES(i) (GST_VIDEO_FORMAT_INFO_N_PLANES((i)->finfo)) +#define GST_VIDEO_INFO_PLANE_OFFSET(i,p) ((i)->offset[p]) +#define GST_VIDEO_INFO_PLANE_STRIDE(i,p) ((i)->stride[p]) + +/* dealing with components */ +#define GST_VIDEO_INFO_N_COMPONENTS(i) GST_VIDEO_FORMAT_INFO_N_COMPONENTS((i)->finfo) +#define GST_VIDEO_INFO_COMP_DEPTH(i,c) GST_VIDEO_FORMAT_INFO_DEPTH((i)->finfo,c) +#define GST_VIDEO_INFO_COMP_BITS(i,c) GST_VIDEO_FORMAT_INFO_BITS((i)->finfo,c) +#define GST_VIDEO_INFO_COMP_DATA(i,d,c) GST_VIDEO_FORMAT_INFO_DATA((i)->finfo,d,c) +#define GST_VIDEO_INFO_COMP_OFFSET(i,c) GST_VIDEO_FORMAT_INFO_OFFSET((i)->finfo,(i)->offset,c) +#define GST_VIDEO_INFO_COMP_STRIDE(i,c) GST_VIDEO_FORMAT_INFO_STRIDE((i)->finfo,(i)->stride,c) +#define GST_VIDEO_INFO_COMP_WIDTH(i,c) GST_VIDEO_FORMAT_INFO_SCALE_WIDTH((i)->finfo,c,(i)->width) +#define GST_VIDEO_INFO_COMP_HEIGHT(i,c) GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT((i)->finfo,c,(i)->height) +#define GST_VIDEO_INFO_COMP_PLANE(i,c) GST_VIDEO_FORMAT_INFO_PLANE((i)->finfo,c) +#define GST_VIDEO_INFO_COMP_PSTRIDE(i,c) GST_VIDEO_FORMAT_INFO_PSTRIDE((i)->finfo,c) +#define GST_VIDEO_INFO_COMP_POFFSET(i,c) GST_VIDEO_FORMAT_INFO_POFFSET((i)->finfo,c) + +void gst_video_info_init (GstVideoInfo *info); + +void gst_video_info_set_format (GstVideoInfo *info, GstVideoFormat format, + guint width, guint height); + +gboolean gst_video_info_from_caps (GstVideoInfo *info, const GstCaps * caps); + +GstCaps * gst_video_info_to_caps (GstVideoInfo *info); + +gboolean gst_video_info_convert (GstVideoInfo *info, + GstFormat src_format, + gint64 src_value, + GstFormat dest_format, + gint64 *dest_value); + /* functions */ const GValue * gst_video_frame_rate (GstPad * pad); @@ -493,11 +954,17 @@ GstCaps * gst_video_format_new_caps_interlaced (GstVideoFormat format, GstCaps * gst_video_format_new_template_caps (GstVideoFormat format); /* format properties */ +GstVideoFormat gst_video_format_from_masks (gint depth, gint bpp, gint endianness, + gint red_mask, gint green_mask, + gint blue_mask, gint alpha_mask) G_GNUC_CONST; + GstVideoFormat gst_video_format_from_fourcc (guint32 fourcc) G_GNUC_CONST; guint32 gst_video_format_to_fourcc (GstVideoFormat format) G_GNUC_CONST; +const gchar * gst_video_format_to_string (GstVideoFormat format) G_GNUC_CONST; + gboolean gst_video_format_is_rgb (GstVideoFormat format) G_GNUC_CONST; gboolean gst_video_format_is_yuv (GstVideoFormat format) G_GNUC_CONST; diff --git a/tests/check/libs/video.c b/tests/check/libs/video.c index 4abd0b37ab..02d552241b 100644 --- a/tests/check/libs/video.c +++ b/tests/check/libs/video.c @@ -369,6 +369,7 @@ GST_START_TEST (test_video_formats) guint i; for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) { + const GstVideoFormatInfo *vf_info; GstVideoFormat fmt; const gchar *s; guint32 fourcc; @@ -378,8 +379,15 @@ GST_START_TEST (test_video_formats) fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]); fmt = gst_video_format_from_fourcc (fourcc); - if (fmt == GST_VIDEO_FORMAT_UNKNOWN) + if (fmt == GST_VIDEO_FORMAT_UNKNOWN) { + GST_DEBUG ("Unknown format %s, skipping tests", fourcc_list[i].fourcc); continue; + } + + vf_info = gst_video_format_get_info (fmt); + fail_unless (vf_info != NULL); + + fail_unless_equals_int (GST_VIDEO_FORMAT_INFO_FORMAT (vf_info), fmt); GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc, gst_video_format_is_packed (fmt)); @@ -410,8 +418,8 @@ GST_START_TEST (test_video_formats) fourcc_list[i].paint_setup (&paintinfo, NULL); fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 0, w), paintinfo.ystride); - if (!gst_video_format_is_packed (fmt) - && !gst_video_format_is_gray (fmt)) { + if (GST_VIDEO_FORMAT_INFO_N_COMPONENTS (vf_info) > 1 && + !gst_video_format_is_packed (fmt)) { /* planar */ fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 1, w), paintinfo.ustride);