mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 06:16:36 +00:00
8379d20ec6
Determine chroma site position from the caps and use it when upsampling/downsampling chroma.
989 lines
28 KiB
C
989 lines
28 KiB
C
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <cog/cog.h>
|
|
#include <cog/cogframe.h>
|
|
#include <cog/cogvirtframe.h>
|
|
#include "cogorc.h"
|
|
#include <gst/gst.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
/**
|
|
* cog_frame_new:
|
|
*
|
|
* Creates a new CogFrame object. The created frame is uninitialized
|
|
* and has no data storage associated with it. The caller must fill
|
|
* in the required information.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new (void)
|
|
{
|
|
CogFrame *frame;
|
|
|
|
frame = g_malloc0 (sizeof (*frame));
|
|
frame->refcount = 1;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_and_alloc:
|
|
*
|
|
* Creates a new CogFrame object with the requested size and format.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_and_alloc (CogMemoryDomain * domain, CogFrameFormat format,
|
|
int width, int height)
|
|
{
|
|
return cog_frame_new_and_alloc_extended (domain, format, width, height, 0);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_and_alloc_extended (CogMemoryDomain * domain,
|
|
CogFrameFormat format, int width, int height, int extension)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
int bytes_pp;
|
|
int h_shift, v_shift;
|
|
int chroma_width;
|
|
int chroma_height;
|
|
int ext_width;
|
|
int ext_height;
|
|
|
|
g_return_val_if_fail (width > 0, NULL);
|
|
g_return_val_if_fail (height > 0, NULL);
|
|
|
|
frame->format = format;
|
|
frame->width = width;
|
|
frame->height = height;
|
|
frame->domain = domain;
|
|
frame->extension = extension;
|
|
|
|
ext_width = width + extension * 2;
|
|
ext_height = height + extension * 2;
|
|
|
|
if (COG_FRAME_IS_PACKED (format)) {
|
|
g_return_val_if_fail (extension == 0, NULL);
|
|
|
|
frame->components[0].format = format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
if (format == COG_FRAME_FORMAT_AYUV) {
|
|
frame->components[0].stride = width * 4;
|
|
} else {
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 2;
|
|
}
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
|
|
frame->regions[0] = g_malloc (frame->components[0].length);
|
|
|
|
frame->components[0].data = frame->regions[0];
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
switch (COG_FRAME_FORMAT_DEPTH (format)) {
|
|
case COG_FRAME_FORMAT_DEPTH_U8:
|
|
bytes_pp = 1;
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S16:
|
|
bytes_pp = 2;
|
|
break;
|
|
case COG_FRAME_FORMAT_DEPTH_S32:
|
|
bytes_pp = 4;
|
|
break;
|
|
default:
|
|
g_return_val_if_reached (NULL);
|
|
bytes_pp = 0;
|
|
break;
|
|
}
|
|
|
|
h_shift = COG_FRAME_FORMAT_H_SHIFT (format);
|
|
v_shift = COG_FRAME_FORMAT_V_SHIFT (format);
|
|
chroma_width = ROUND_UP_SHIFT (width, h_shift);
|
|
chroma_height = ROUND_UP_SHIFT (height, v_shift);
|
|
|
|
frame->components[0].format = format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_4 ((width + extension * 2) * bytes_pp);
|
|
frame->components[0].length =
|
|
frame->components[0].stride * (frame->components[0].height +
|
|
extension * 2);
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->components[1].format = format;
|
|
frame->components[1].width = chroma_width;
|
|
frame->components[1].height = chroma_height;
|
|
frame->components[1].stride =
|
|
ROUND_UP_4 ((chroma_width + extension * 2) * bytes_pp);
|
|
frame->components[1].length =
|
|
frame->components[1].stride * (frame->components[1].height +
|
|
extension * 2);
|
|
frame->components[1].v_shift = v_shift;
|
|
frame->components[1].h_shift = h_shift;
|
|
|
|
frame->components[2].format = format;
|
|
frame->components[2].width = chroma_width;
|
|
frame->components[2].height = chroma_height;
|
|
frame->components[2].stride =
|
|
ROUND_UP_4 ((chroma_width + extension * 2) * bytes_pp);
|
|
frame->components[2].length =
|
|
frame->components[2].stride * (frame->components[2].height +
|
|
extension * 2);
|
|
frame->components[2].v_shift = v_shift;
|
|
frame->components[2].h_shift = h_shift;
|
|
|
|
frame->regions[0] = malloc (frame->components[0].length +
|
|
frame->components[1].length + frame->components[2].length);
|
|
|
|
frame->components[0].data = COG_OFFSET (frame->regions[0],
|
|
frame->components[0].stride * extension + bytes_pp * extension);
|
|
frame->components[1].data = COG_OFFSET (frame->regions[0],
|
|
frame->components[0].length +
|
|
frame->components[1].stride * extension + bytes_pp * extension);
|
|
frame->components[2].data = COG_OFFSET (frame->regions[0],
|
|
frame->components[0].length + frame->components[1].length +
|
|
frame->components[2].stride * extension + bytes_pp * extension);
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_YUY2:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in YUY2 format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_YUY2 (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_YUYV;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 2;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_YUY2:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in UYVY format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_UYVY (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_UYVY;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 2;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_YUY2:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in UYVY format,
|
|
* although the row stride is allowed to be different than what
|
|
* would normally be calculated from @width.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_UYVY_full (void *data, int width, int height,
|
|
int stride)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_UYVY;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = stride;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_AYUV:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in AYUV format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_AYUV (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_AYUV;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = width * 4;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_v216:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in v216 format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_v216 (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_v216;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 1) * 4;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_v210:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in v210 format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_v210 (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_v210;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ((width + 47) / 48) * 128;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_I420:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in I420 format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_I420 (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_U8_420;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 2);
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride *
|
|
ROUND_UP_POW2 (frame->components[0].height, 1);
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->components[1].format = frame->format;
|
|
frame->components[1].width = ROUND_UP_SHIFT (width, 1);
|
|
frame->components[1].height = ROUND_UP_SHIFT (height, 1);
|
|
frame->components[1].stride = ROUND_UP_POW2 (frame->components[1].width, 2);
|
|
frame->components[1].length =
|
|
frame->components[1].stride * frame->components[1].height;
|
|
frame->components[1].data =
|
|
COG_OFFSET (frame->components[0].data, frame->components[0].length);
|
|
frame->components[1].v_shift = 1;
|
|
frame->components[1].h_shift = 1;
|
|
|
|
frame->components[2].format = frame->format;
|
|
frame->components[2].width = ROUND_UP_SHIFT (width, 1);
|
|
frame->components[2].height = ROUND_UP_SHIFT (height, 1);
|
|
frame->components[2].stride = ROUND_UP_POW2 (frame->components[2].width, 2);
|
|
frame->components[2].length =
|
|
frame->components[2].stride * frame->components[2].height;
|
|
frame->components[2].data =
|
|
COG_OFFSET (frame->components[1].data, frame->components[1].length);
|
|
frame->components[2].v_shift = 1;
|
|
frame->components[2].h_shift = 1;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_YV12:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in YV12 format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_YV12 (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_U8_420;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 2);
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride *
|
|
ROUND_UP_POW2 (frame->components[0].height, 1);
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->components[2].format = frame->format;
|
|
frame->components[2].width = ROUND_UP_SHIFT (width, 1);
|
|
frame->components[2].height = ROUND_UP_SHIFT (height, 1);
|
|
frame->components[2].stride = ROUND_UP_POW2 (frame->components[2].width, 2);
|
|
frame->components[2].length =
|
|
frame->components[2].stride * frame->components[2].height;
|
|
frame->components[2].data =
|
|
COG_OFFSET (frame->components[0].data, frame->components[0].length);
|
|
frame->components[2].v_shift = 1;
|
|
frame->components[2].h_shift = 1;
|
|
|
|
frame->components[1].format = frame->format;
|
|
frame->components[1].width = ROUND_UP_SHIFT (width, 1);
|
|
frame->components[1].height = ROUND_UP_SHIFT (height, 1);
|
|
frame->components[1].stride = ROUND_UP_POW2 (frame->components[1].width, 2);
|
|
frame->components[1].length =
|
|
frame->components[1].stride * frame->components[1].height;
|
|
frame->components[1].data =
|
|
COG_OFFSET (frame->components[2].data, frame->components[2].length);
|
|
frame->components[1].v_shift = 1;
|
|
frame->components[1].h_shift = 1;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_Y42B:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in Y42B format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_Y42B (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_U8_422;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 2);
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride *
|
|
ROUND_UP_POW2 (frame->components[0].height, 1);
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->components[1].format = frame->format;
|
|
frame->components[1].width = ROUND_UP_SHIFT (width, 1);
|
|
frame->components[1].height = height;
|
|
frame->components[1].stride = ROUND_UP_POW2 (frame->components[1].width, 2);
|
|
frame->components[1].length =
|
|
frame->components[1].stride * frame->components[1].height;
|
|
frame->components[1].data =
|
|
COG_OFFSET (frame->components[0].data, frame->components[0].length);
|
|
frame->components[1].v_shift = 0;
|
|
frame->components[1].h_shift = 1;
|
|
|
|
frame->components[2].format = frame->format;
|
|
frame->components[2].width = ROUND_UP_SHIFT (width, 1);
|
|
frame->components[2].height = height;
|
|
frame->components[2].stride = ROUND_UP_POW2 (frame->components[2].width, 2);
|
|
frame->components[2].length =
|
|
frame->components[2].stride * frame->components[2].height;
|
|
frame->components[2].data =
|
|
COG_OFFSET (frame->components[1].data, frame->components[1].length);
|
|
frame->components[2].v_shift = 0;
|
|
frame->components[2].h_shift = 1;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_Y444:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in Y444 format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_Y444 (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_U8_444;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].format = frame->format;
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_POW2 (width, 4);
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride *
|
|
ROUND_UP_POW2 (frame->components[0].height, 1);
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
frame->components[1].format = frame->format;
|
|
frame->components[1].width = width;
|
|
frame->components[1].height = height;
|
|
frame->components[1].stride = ROUND_UP_POW2 (width, 4);
|
|
frame->components[1].length =
|
|
frame->components[1].stride * frame->components[1].height;
|
|
frame->components[1].data =
|
|
COG_OFFSET (frame->components[0].data, frame->components[0].length);
|
|
frame->components[1].v_shift = 0;
|
|
frame->components[1].h_shift = 0;
|
|
|
|
frame->components[2].format = frame->format;
|
|
frame->components[2].width = width;
|
|
frame->components[2].height = height;
|
|
frame->components[2].stride = ROUND_UP_POW2 (width, 4);
|
|
frame->components[2].length =
|
|
frame->components[2].stride * frame->components[2].height;
|
|
frame->components[2].data =
|
|
COG_OFFSET (frame->components[1].data, frame->components[1].length);
|
|
frame->components[2].v_shift = 0;
|
|
frame->components[2].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_new_from_data_RGB:
|
|
*
|
|
* Creates a new CogFrame object with the requested size using
|
|
* the data pointed to by @data. The data must be in RGB format.
|
|
* The data must remain for the lifetime of the CogFrame object.
|
|
* It is recommended to use cog_frame_set_free_callback() for
|
|
* notification when the data is no longer needed.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_new_from_data_RGB (void *data, int width, int height)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = COG_FRAME_FORMAT_RGB;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = ROUND_UP_4 (width * 3);
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
static CogFrame *
|
|
cog_frame_new_from_data_RGB32 (void *data, int width, int height, int format)
|
|
{
|
|
CogFrame *frame = cog_frame_new ();
|
|
|
|
frame->format = format;
|
|
|
|
frame->width = width;
|
|
frame->height = height;
|
|
|
|
frame->components[0].width = width;
|
|
frame->components[0].height = height;
|
|
frame->components[0].stride = width * 4;
|
|
frame->components[0].data = data;
|
|
frame->components[0].length = frame->components[0].stride * height;
|
|
frame->components[0].v_shift = 0;
|
|
frame->components[0].h_shift = 0;
|
|
|
|
return frame;
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_RGBx (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_RGBx);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_xRGB (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_xRGB);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_BGRx (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_BGRx);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_xBGR (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_xBGR);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_RGBA (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_RGBA);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_ARGB (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_ARGB);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_BGRA (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_BGRA);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_new_from_data_ABGR (void *data, int width, int height)
|
|
{
|
|
return cog_frame_new_from_data_RGB32 (data, width, height,
|
|
COG_FRAME_FORMAT_ABGR);
|
|
}
|
|
|
|
/**
|
|
* cog_frame_dup:
|
|
*
|
|
* Creates a new CogFrame object with the same dimensions and format
|
|
* as @frame, and copies the data from the @frame to the new object.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_dup (CogFrame * frame)
|
|
{
|
|
return cog_frame_dup_extended (frame, 0);
|
|
}
|
|
|
|
CogFrame *
|
|
cog_frame_dup_extended (CogFrame * frame, int extension)
|
|
{
|
|
CogFrame *dup_frame;
|
|
|
|
dup_frame = cog_frame_new_and_alloc_extended (frame->domain,
|
|
frame->format, frame->width, frame->height, extension);
|
|
cog_frame_convert (dup_frame, frame);
|
|
|
|
return dup_frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_clone:
|
|
*
|
|
* Creates a new CogFrame object with the same dimensions and format
|
|
* as @frame. This function leaves the data in the new object
|
|
* uninitialized.
|
|
*
|
|
* Returns: a new CogFrame object
|
|
*/
|
|
CogFrame *
|
|
cog_frame_clone (CogMemoryDomain * domain, CogFrame * frame)
|
|
{
|
|
return cog_frame_new_and_alloc (domain,
|
|
frame->format, frame->width, frame->height);
|
|
}
|
|
|
|
/**
|
|
* cog_frame_ref:
|
|
* @frame: a frame object
|
|
*
|
|
* Increases the reference count of @frame.
|
|
*
|
|
* Returns: the value of @frame
|
|
*/
|
|
CogFrame *
|
|
cog_frame_ref (CogFrame * frame)
|
|
{
|
|
frame->refcount++;
|
|
return frame;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_unref:
|
|
* @frame: a frame object
|
|
*
|
|
* Decreases the reference count of @frame. If the new reference
|
|
* count is 0, the frame is freed. If a frame free callback was
|
|
* set, this function is called.
|
|
*
|
|
* Returns: the value of @frame
|
|
*/
|
|
void
|
|
cog_frame_unref (CogFrame * frame)
|
|
{
|
|
int i;
|
|
|
|
g_return_if_fail (frame->refcount > 0);
|
|
|
|
frame->refcount--;
|
|
if (frame->refcount == 0) {
|
|
if (frame->free) {
|
|
frame->free (frame, frame->priv);
|
|
}
|
|
#ifdef HAVE_OPENGL
|
|
if (COG_FRAME_IS_OPENGL (frame)) {
|
|
cog_opengl_frame_cleanup (frame);
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
if (frame->regions[i]) {
|
|
g_free (frame->regions[i]);
|
|
}
|
|
}
|
|
|
|
if (frame->virt_frame1) {
|
|
cog_frame_unref (frame->virt_frame1);
|
|
}
|
|
if (frame->virt_frame2) {
|
|
cog_frame_unref (frame->virt_frame2);
|
|
}
|
|
if (frame->virt_priv) {
|
|
g_free (frame->virt_priv);
|
|
}
|
|
|
|
g_free (frame);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* cog_frame_set_free_callback:
|
|
* @frame: a frame object
|
|
* @free_func: the function to call when the frame is freed
|
|
* @priv: callback key
|
|
*
|
|
* Sets a function that will be called when the object reference
|
|
* count drops to zero and the object is freed.
|
|
*/
|
|
void
|
|
cog_frame_set_free_callback (CogFrame * frame,
|
|
CogFrameFreeFunc free_func, void *priv)
|
|
{
|
|
frame->free = free_func;
|
|
frame->priv = priv;
|
|
}
|
|
|
|
/**
|
|
* cog_frame_convert:
|
|
* @dest: destination frame
|
|
* @src: source frame
|
|
*
|
|
* Copies data from the source frame to the destination frame, converting
|
|
* formats if necessary. Only a few conversions are supported.
|
|
*/
|
|
void
|
|
cog_frame_convert (CogFrame * dest, CogFrame * src)
|
|
{
|
|
CogFrame *frame;
|
|
CogFrameFormat dest_format;
|
|
|
|
g_return_if_fail (dest != NULL);
|
|
g_return_if_fail (src != NULL);
|
|
|
|
switch (dest->format) {
|
|
case COG_FRAME_FORMAT_YUYV:
|
|
case COG_FRAME_FORMAT_UYVY:
|
|
dest_format = COG_FRAME_FORMAT_U8_422;
|
|
break;
|
|
case COG_FRAME_FORMAT_AYUV:
|
|
case COG_FRAME_FORMAT_ARGB:
|
|
dest_format = COG_FRAME_FORMAT_U8_444;
|
|
break;
|
|
default:
|
|
dest_format = dest->format;
|
|
break;
|
|
}
|
|
cog_frame_ref (src);
|
|
|
|
frame = cog_virt_frame_new_unpack (src);
|
|
GST_DEBUG ("unpack %p", frame);
|
|
|
|
if (COG_FRAME_FORMAT_DEPTH (dest_format) !=
|
|
COG_FRAME_FORMAT_DEPTH (frame->format)) {
|
|
if (COG_FRAME_FORMAT_DEPTH (dest_format) == COG_FRAME_FORMAT_DEPTH_U8) {
|
|
frame = cog_virt_frame_new_convert_u8 (frame);
|
|
GST_DEBUG ("convert_u8 %p", frame);
|
|
} else if (COG_FRAME_FORMAT_DEPTH (dest_format) ==
|
|
COG_FRAME_FORMAT_DEPTH_S16) {
|
|
frame = cog_virt_frame_new_convert_s16 (frame);
|
|
GST_DEBUG ("convert_s16 %p", frame);
|
|
}
|
|
}
|
|
|
|
if ((dest_format & 3) != (frame->format & 3)) {
|
|
frame = cog_virt_frame_new_subsample (frame, dest_format,
|
|
COG_CHROMA_SITE_MPEG2, 2);
|
|
GST_DEBUG ("subsample %p", frame);
|
|
}
|
|
|
|
switch (dest->format) {
|
|
case COG_FRAME_FORMAT_YUYV:
|
|
frame = cog_virt_frame_new_pack_YUY2 (frame);
|
|
GST_DEBUG ("pack_YUY2 %p", frame);
|
|
break;
|
|
case COG_FRAME_FORMAT_UYVY:
|
|
frame = cog_virt_frame_new_pack_UYVY (frame);
|
|
GST_DEBUG ("pack_UYVY %p", frame);
|
|
break;
|
|
case COG_FRAME_FORMAT_AYUV:
|
|
frame = cog_virt_frame_new_pack_AYUV (frame);
|
|
GST_DEBUG ("pack_AYUV %p", frame);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (dest->width < frame->width || dest->height < frame->height) {
|
|
GST_DEBUG ("crop %d %d to %d %d",
|
|
frame->width, frame->height, dest->width, dest->height);
|
|
|
|
frame = cog_virt_frame_new_crop (frame, dest->width, dest->height);
|
|
GST_DEBUG ("crop %p", frame);
|
|
}
|
|
if (dest->width > src->width || dest->height > src->height) {
|
|
frame = cog_virt_frame_new_edgeextend (frame, dest->width, dest->height);
|
|
GST_DEBUG ("edgeextend %p", frame);
|
|
}
|
|
|
|
cog_virt_frame_render (frame, dest);
|
|
cog_frame_unref (frame);
|
|
|
|
}
|
|
|
|
|
|
#if 0
|
|
void
|
|
cog_frame_md5 (CogFrame * frame, uint32_t * state)
|
|
{
|
|
uint8_t *line;
|
|
int x, y, k;
|
|
|
|
state[0] = 0x67452301;
|
|
state[1] = 0xefcdab89;
|
|
state[2] = 0x98badcfe;
|
|
state[3] = 0x10325476;
|
|
|
|
x = 0;
|
|
y = 0;
|
|
k = 0;
|
|
for (k = 0; k < 3; k++) {
|
|
for (y = 0; y < frame->components[k].height; y++) {
|
|
line = COG_FRAME_DATA_GET_LINE (&frame->components[k], y);
|
|
for (x = 0; x + 63 < frame->components[k].width; x += 64) {
|
|
oil_md5 (state, (uint32_t *) (line + x));
|
|
}
|
|
if (x < frame->components[k].width) {
|
|
uint8_t tmp[64];
|
|
int left;
|
|
left = frame->components[k].width - x;
|
|
memcpy (tmp, line + x, left);
|
|
memset (tmp + left, 0, 64 - left);
|
|
oil_md5 (state, (uint32_t *) tmp);
|
|
}
|
|
}
|
|
}
|
|
|
|
GST_DEBUG
|
|
("md5 %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
|
|
state[0] & 0xff, (state[0] >> 8) & 0xff, (state[0] >> 16) & 0xff,
|
|
(state[0] >> 24) & 0xff, state[1] & 0xff, (state[1] >> 8) & 0xff,
|
|
(state[1] >> 16) & 0xff, (state[1] >> 24) & 0xff, state[2] & 0xff,
|
|
(state[2] >> 8) & 0xff, (state[2] >> 16) & 0xff, (state[2] >> 24) & 0xff,
|
|
state[3] & 0xff, (state[3] >> 8) & 0xff, (state[3] >> 16) & 0xff,
|
|
(state[3] >> 24) & 0xff);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
cog_frame_split_fields (CogFrame * dest1, CogFrame * dest2, CogFrame * src)
|
|
{
|
|
CogFrame src_tmp;
|
|
|
|
g_return_if_fail ((src->height & 1) == 0);
|
|
|
|
memcpy (&src_tmp, src, sizeof (src_tmp));
|
|
|
|
src_tmp.height = src->height / 2;
|
|
src_tmp.components[0].stride *= 2;
|
|
src_tmp.components[1].stride *= 2;
|
|
src_tmp.components[2].stride *= 2;
|
|
|
|
cog_frame_convert (dest1, &src_tmp);
|
|
|
|
src_tmp.components[0].data = COG_FRAME_DATA_GET_LINE (&src->components[0], 1);
|
|
src_tmp.components[1].data = COG_FRAME_DATA_GET_LINE (&src->components[1], 1);
|
|
src_tmp.components[2].data = COG_FRAME_DATA_GET_LINE (&src->components[2], 1);
|
|
|
|
cog_frame_convert (dest2, &src_tmp);
|
|
}
|
|
|
|
void
|
|
cog_frame_get_subdata (CogFrame * frame, CogFrameData * fd,
|
|
int component, int x, int y)
|
|
{
|
|
CogFrameData *comp = frame->components + component;
|
|
|
|
g_return_if_fail (COG_FRAME_FORMAT_DEPTH (comp->format) ==
|
|
COG_FRAME_FORMAT_DEPTH_U8);
|
|
|
|
fd->format = comp->format;
|
|
fd->data = COG_FRAME_DATA_GET_PIXEL_U8 (comp, x, y);
|
|
fd->stride = comp->stride;
|
|
fd->width = MAX (0, comp->width - x);
|
|
fd->height = MAX (0, comp->height - y);
|
|
fd->h_shift = comp->h_shift;
|
|
fd->v_shift = comp->v_shift;
|
|
}
|