mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-04 09:42:19 +00:00
applemedia: port vtdec
This commit is contained in:
parent
b45250e9d2
commit
8546458617
7 changed files with 164 additions and 87 deletions
|
@ -78,6 +78,7 @@ else
|
||||||
|
|
||||||
libgstapplemedia_la_SOURCES += \
|
libgstapplemedia_la_SOURCES += \
|
||||||
qtkitvideosrc.m \
|
qtkitvideosrc.m \
|
||||||
|
vtdec.c \
|
||||||
mioapi.c
|
mioapi.c
|
||||||
|
|
||||||
libgstapplemedia_la_LDFLAGS += \
|
libgstapplemedia_la_LDFLAGS += \
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
|
|
||||||
- (GstBuffer *)createGstBufferForCoreVideoBuffer:(CFTypeRef)cvbuf
|
- (GstBuffer *)createGstBufferForCoreVideoBuffer:(CFTypeRef)cvbuf
|
||||||
{
|
{
|
||||||
return gst_core_video_buffer_new (coreMediaCtx, (CVBufferRef) cvbuf);
|
return gst_core_video_buffer_new (coreMediaCtx, (CVBufferRef) cvbuf, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (GstBuffer *)createGstBufferForSampleBuffer:(CFTypeRef)sbuf
|
- (GstBuffer *)createGstBufferForSampleBuffer:(CFTypeRef)sbuf
|
||||||
|
|
|
@ -49,7 +49,8 @@ gst_core_video_meta_get_info (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
GstBuffer *
|
GstBuffer *
|
||||||
gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf)
|
gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf,
|
||||||
|
GstVideoInfo * vinfo)
|
||||||
{
|
{
|
||||||
GstCVApi *cv = ctx->cv;
|
GstCVApi *cv = ctx->cv;
|
||||||
void *data;
|
void *data;
|
||||||
|
@ -57,32 +58,65 @@ gst_core_video_buffer_new (GstCoreMediaCtx * ctx, CVBufferRef cvbuf)
|
||||||
CVPixelBufferRef pixbuf = NULL;
|
CVPixelBufferRef pixbuf = NULL;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
GstCoreVideoMeta *meta;
|
GstCoreVideoMeta *meta;
|
||||||
|
guint width, height, n_planes, i;
|
||||||
|
gsize offset[GST_VIDEO_MAX_PLANES];
|
||||||
|
gint stride[GST_VIDEO_MAX_PLANES];
|
||||||
|
|
||||||
if (CFGetTypeID (cvbuf) == cv->CVPixelBufferGetTypeID ()) {
|
if (CFGetTypeID (cvbuf) != cv->CVPixelBufferGetTypeID ())
|
||||||
pixbuf = (CVPixelBufferRef) cvbuf;
|
|
||||||
|
|
||||||
if (cv->CVPixelBufferLockBaseAddress (pixbuf,
|
|
||||||
kCVPixelBufferLock_ReadOnly) != kCVReturnSuccess) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
data = cv->CVPixelBufferGetBaseAddress (pixbuf);
|
|
||||||
size = cv->CVPixelBufferGetBytesPerRow (pixbuf) *
|
|
||||||
cv->CVPixelBufferGetHeight (pixbuf);
|
|
||||||
} else {
|
|
||||||
/* TODO: Do we need to handle other buffer types? */
|
/* TODO: Do we need to handle other buffer types? */
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
pixbuf = (CVPixelBufferRef) cvbuf;
|
||||||
|
|
||||||
|
if (cv->CVPixelBufferLockBaseAddress (pixbuf,
|
||||||
|
kCVPixelBufferLock_ReadOnly) != kCVReturnSuccess) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = gst_buffer_new ();
|
buf = gst_buffer_new ();
|
||||||
|
|
||||||
|
/* add the corevideo meta to free the underlying corevideo buffer */
|
||||||
meta = (GstCoreVideoMeta *) gst_buffer_add_meta (buf,
|
meta = (GstCoreVideoMeta *) gst_buffer_add_meta (buf,
|
||||||
gst_core_video_meta_get_info (), NULL);
|
gst_core_video_meta_get_info (), NULL);
|
||||||
meta->ctx = g_object_ref (ctx);
|
meta->ctx = g_object_ref (ctx);
|
||||||
meta->cvbuf = cv->CVBufferRetain (cvbuf);
|
meta->cvbuf = cv->CVBufferRetain (cvbuf);
|
||||||
meta->pixbuf = pixbuf;
|
meta->pixbuf = pixbuf;
|
||||||
|
|
||||||
|
/* set stride, offset and size */
|
||||||
|
memset (&offset, 0, sizeof (offset));
|
||||||
|
memset (&stride, 0, sizeof (stride));
|
||||||
|
|
||||||
|
data = cv->CVPixelBufferGetBaseAddress (pixbuf);
|
||||||
|
height = cv->CVPixelBufferGetHeight (pixbuf);
|
||||||
|
if (cv->CVPixelBufferIsPlanar (pixbuf)) {
|
||||||
|
GstVideoInfo tmp_vinfo;
|
||||||
|
|
||||||
|
n_planes = cv->CVPixelBufferGetPlaneCount (pixbuf);
|
||||||
|
for (i = 0; i < n_planes; ++i)
|
||||||
|
stride[i] = cv->CVPixelBufferGetBytesPerRowOfPlane (pixbuf, i);
|
||||||
|
|
||||||
|
/* FIXME: don't hardcode NV12 */
|
||||||
|
gst_video_info_set_format (&tmp_vinfo,
|
||||||
|
GST_VIDEO_FORMAT_NV12, stride[0], height);
|
||||||
|
offset[1] = tmp_vinfo.offset[1];
|
||||||
|
size = tmp_vinfo.size;
|
||||||
|
} else {
|
||||||
|
n_planes = 1;
|
||||||
|
size = cv->CVPixelBufferGetBytesPerRow (pixbuf) * height;
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_take_memory (buf, -1,
|
gst_buffer_take_memory (buf, -1,
|
||||||
gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
|
gst_memory_new_wrapped (GST_MEMORY_FLAG_NO_SHARE, data,
|
||||||
size, 0, size, NULL, NULL));
|
size, 0, size, NULL, NULL));
|
||||||
|
|
||||||
|
if (vinfo) {
|
||||||
|
GstVideoMeta *video_meta;
|
||||||
|
|
||||||
|
width = vinfo->width;
|
||||||
|
video_meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FLAG_NONE,
|
||||||
|
GST_VIDEO_FORMAT_NV12, width, height, n_planes, offset, stride);
|
||||||
|
}
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#define __GST_CORE_VIDEO_BUFFER_H__
|
#define __GST_CORE_VIDEO_BUFFER_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideometa.h>
|
||||||
|
|
||||||
#include "coremediactx.h"
|
#include "coremediactx.h"
|
||||||
|
|
||||||
|
@ -36,7 +38,8 @@ typedef struct _GstCoreVideoMeta
|
||||||
} GstCoreVideoMeta;
|
} GstCoreVideoMeta;
|
||||||
|
|
||||||
GstBuffer * gst_core_video_buffer_new (GstCoreMediaCtx * ctx,
|
GstBuffer * gst_core_video_buffer_new (GstCoreMediaCtx * ctx,
|
||||||
CVBufferRef cvbuf);
|
CVBufferRef cvbuf,
|
||||||
|
GstVideoInfo *info);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -73,8 +73,8 @@ plugin_init (GstPlugin * plugin)
|
||||||
GST_TYPE_VT_H264_ENC_BIN);
|
GST_TYPE_VT_H264_ENC_BIN);
|
||||||
|
|
||||||
gst_vtenc_register_elements (plugin);
|
gst_vtenc_register_elements (plugin);
|
||||||
gst_vtdec_register_elements (plugin);
|
|
||||||
#endif
|
#endif
|
||||||
|
gst_vtdec_register_elements (plugin);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,9 @@ static GstElementClass *parent_class = NULL;
|
||||||
|
|
||||||
static GstStateChangeReturn gst_vtdec_change_state (GstElement * element,
|
static GstStateChangeReturn gst_vtdec_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
static gboolean gst_vtdec_sink_setcaps (GstPad * pad, GstCaps * caps);
|
static gboolean gst_vtdec_sink_setcaps (GstVTDec * dec, GstCaps * caps);
|
||||||
static GstFlowReturn gst_vtdec_chain (GstPad * pad, GstBuffer * buf);
|
static GstFlowReturn gst_vtdec_chain (GstPad * pad, GstObject * parent,
|
||||||
|
GstBuffer * buf);
|
||||||
|
|
||||||
static CMFormatDescriptionRef gst_vtdec_create_format_description
|
static CMFormatDescriptionRef gst_vtdec_create_format_description
|
||||||
(GstVTDec * self);
|
(GstVTDec * self);
|
||||||
|
@ -47,6 +48,8 @@ static void gst_vtdec_destroy_session (GstVTDec * self,
|
||||||
static GstFlowReturn gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf);
|
static GstFlowReturn gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf);
|
||||||
static void gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result,
|
static void gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result,
|
||||||
gsize unk2, CVBufferRef cvbuf);
|
gsize unk2, CVBufferRef cvbuf);
|
||||||
|
static gboolean gst_vtdec_sink_event (GstPad * pad, GstObject * parent,
|
||||||
|
GstEvent * event);
|
||||||
|
|
||||||
static CMSampleBufferRef gst_vtdec_sample_buffer_from (GstVTDec * self,
|
static CMSampleBufferRef gst_vtdec_sample_buffer_from (GstVTDec * self,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
|
@ -63,19 +66,17 @@ gst_vtdec_base_init (GstVTDecClass * klass)
|
||||||
const int min_fps_d = 1, max_fps_d = 1;
|
const int min_fps_d = 1, max_fps_d = 1;
|
||||||
GstPadTemplate *sink_template, *src_template;
|
GstPadTemplate *sink_template, *src_template;
|
||||||
GstCaps *sink_caps;
|
GstCaps *sink_caps;
|
||||||
GstElementDetails details;
|
gchar *longname, *description;
|
||||||
|
|
||||||
details.longname = g_strdup_printf ("%s decoder", codec_details->name);
|
longname = g_strdup_printf ("%s decoder", codec_details->name);
|
||||||
details.klass = g_strdup_printf ("Codec/Decoder/Video");
|
description = g_strdup_printf ("%s decoder", codec_details->name);
|
||||||
details.description = g_strdup_printf ("%s decoder", codec_details->name);
|
|
||||||
|
|
||||||
gst_element_class_set_details_simple (element_class,
|
gst_element_class_set_metadata (element_class, longname,
|
||||||
details.longname, details.klass, details.description,
|
"Codec/Decoder/Video", description,
|
||||||
"Ole André Vadla Ravnås <oravnas@cisco.com>");
|
"Ole André Vadla Ravnås <oravnas@cisco.com>");
|
||||||
|
|
||||||
g_free (details.longname);
|
g_free (longname);
|
||||||
g_free (details.klass);
|
g_free (description);
|
||||||
g_free (details.description);
|
|
||||||
|
|
||||||
sink_caps = gst_caps_new_simple (codec_details->mimetype,
|
sink_caps = gst_caps_new_simple (codec_details->mimetype,
|
||||||
"width", GST_TYPE_INT_RANGE, min_width, max_width,
|
"width", GST_TYPE_INT_RANGE, min_width, max_width,
|
||||||
|
@ -93,8 +94,8 @@ gst_vtdec_base_init (GstVTDecClass * klass)
|
||||||
src_template = gst_pad_template_new ("src",
|
src_template = gst_pad_template_new ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
gst_caps_new_simple ("video/x-raw-yuv",
|
gst_caps_new_simple ("video/x-raw",
|
||||||
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '1', '2'),
|
"format", G_TYPE_STRING, "NV12",
|
||||||
"width", GST_TYPE_INT_RANGE, min_width, max_width,
|
"width", GST_TYPE_INT_RANGE, min_width, max_width,
|
||||||
"height", GST_TYPE_INT_RANGE, min_height, max_height,
|
"height", GST_TYPE_INT_RANGE, min_height, max_height,
|
||||||
"framerate", GST_TYPE_FRACTION_RANGE,
|
"framerate", GST_TYPE_FRACTION_RANGE,
|
||||||
|
@ -126,7 +127,7 @@ gst_vtdec_init (GstVTDec * self)
|
||||||
self->sinkpad = gst_pad_new_from_template
|
self->sinkpad = gst_pad_new_from_template
|
||||||
(gst_element_class_get_pad_template (element_klass, "sink"), "sink");
|
(gst_element_class_get_pad_template (element_klass, "sink"), "sink");
|
||||||
gst_element_add_pad (element, self->sinkpad);
|
gst_element_add_pad (element, self->sinkpad);
|
||||||
gst_pad_set_setcaps_function (self->sinkpad, gst_vtdec_sink_setcaps);
|
gst_pad_set_event_function (self->sinkpad, gst_vtdec_sink_event);
|
||||||
gst_pad_set_chain_function (self->sinkpad, gst_vtdec_chain);
|
gst_pad_set_chain_function (self->sinkpad, gst_vtdec_chain);
|
||||||
|
|
||||||
self->srcpad = gst_pad_new_from_template
|
self->srcpad = gst_pad_new_from_template
|
||||||
|
@ -158,10 +159,7 @@ gst_vtdec_change_state (GstElement * element, GstStateChange transition)
|
||||||
self->ctx->cm->FigFormatDescriptionRelease (self->fmt_desc);
|
self->ctx->cm->FigFormatDescriptionRelease (self->fmt_desc);
|
||||||
self->fmt_desc = NULL;
|
self->fmt_desc = NULL;
|
||||||
|
|
||||||
self->negotiated_width = self->negotiated_height = 0;
|
gst_video_info_init (&self->vinfo);
|
||||||
self->negotiated_fps_n = self->negotiated_fps_d = 0;
|
|
||||||
self->caps_width = self->caps_height = 0;
|
|
||||||
self->caps_fps_n = self->caps_fps_d = 0;
|
|
||||||
|
|
||||||
g_ptr_array_free (self->cur_outbufs, TRUE);
|
g_ptr_array_free (self->cur_outbufs, TRUE);
|
||||||
self->cur_outbufs = NULL;
|
self->cur_outbufs = NULL;
|
||||||
|
@ -182,25 +180,69 @@ api_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vtdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
gst_vtdec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstVTDec *self = GST_VTDEC_CAST (parent);
|
||||||
|
gboolean forward = TRUE;
|
||||||
|
gboolean res = TRUE;
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_CAPS:
|
||||||
|
{
|
||||||
|
GstCaps *caps;
|
||||||
|
|
||||||
|
gst_event_parse_caps (event, &caps);
|
||||||
|
res = gst_vtdec_sink_setcaps (self, caps);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forward)
|
||||||
|
res = gst_pad_event_default (pad, parent, event);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vtdec_sink_setcaps (GstVTDec * self, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstVTDec *self = GST_VTDEC_CAST (GST_PAD_PARENT (pad));
|
|
||||||
GstStructure *structure;
|
GstStructure *structure;
|
||||||
CMFormatDescriptionRef fmt_desc = NULL;
|
CMFormatDescriptionRef fmt_desc = NULL;
|
||||||
|
GstVideoFormat format = GST_VIDEO_FORMAT_NV12;
|
||||||
|
gint width, height;
|
||||||
|
gint fps_n, fps_d;
|
||||||
|
gint par_n, par_d;
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
if (!gst_structure_get_int (structure, "width", &self->negotiated_width))
|
if (!gst_structure_get_int (structure, "width", &width))
|
||||||
goto incomplete_caps;
|
goto incomplete_caps;
|
||||||
if (!gst_structure_get_int (structure, "height", &self->negotiated_height))
|
if (!gst_structure_get_int (structure, "height", &height))
|
||||||
goto incomplete_caps;
|
goto incomplete_caps;
|
||||||
gst_structure_get_fraction (structure, "framerate",
|
|
||||||
&self->negotiated_fps_n, &self->negotiated_fps_d);
|
|
||||||
|
|
||||||
/* FIXME */
|
gst_video_info_set_format (&self->vinfo, format, width, height);
|
||||||
if (self->negotiated_fps_n == 0)
|
|
||||||
self->negotiated_fps_n = 30;
|
if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
|
||||||
if (self->negotiated_fps_d == 0)
|
if (fps_n == 0) {
|
||||||
self->negotiated_fps_d = 1;
|
/* variable framerate */
|
||||||
|
self->vinfo.flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
|
||||||
|
/* see if we have a max-framerate */
|
||||||
|
gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
|
||||||
|
}
|
||||||
|
self->vinfo.fps_n = fps_n;
|
||||||
|
self->vinfo.fps_d = fps_d;
|
||||||
|
} else {
|
||||||
|
/* unspecified is variable framerate */
|
||||||
|
self->vinfo.fps_n = 0;
|
||||||
|
self->vinfo.fps_d = 1;
|
||||||
|
}
|
||||||
|
if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
|
||||||
|
&par_n, &par_d)) {
|
||||||
|
self->vinfo.par_n = par_n;
|
||||||
|
self->vinfo.par_d = par_d;
|
||||||
|
} else {
|
||||||
|
self->vinfo.par_n = 1;
|
||||||
|
self->vinfo.par_d = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (self->details->format_id == kVTFormatH264) {
|
if (self->details->format_id == kVTFormatH264) {
|
||||||
const GValue *codec_data_value;
|
const GValue *codec_data_value;
|
||||||
|
@ -226,12 +268,14 @@ gst_vtdec_sink_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
goto session_create_error;
|
goto session_create_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* renegotiate when upstream caps change */
|
||||||
|
gst_pad_mark_reconfigure (self->srcpad);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
incomplete_caps:
|
incomplete_caps:
|
||||||
{
|
{
|
||||||
self->negotiated_width = self->negotiated_height = -1;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
session_create_error:
|
session_create_error:
|
||||||
|
@ -245,7 +289,7 @@ session_create_error:
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vtdec_is_negotiated (GstVTDec * self)
|
gst_vtdec_is_negotiated (GstVTDec * self)
|
||||||
{
|
{
|
||||||
return self->negotiated_width != 0;
|
return self->vinfo.width != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -253,42 +297,26 @@ gst_vtdec_negotiate_downstream (GstVTDec * self)
|
||||||
{
|
{
|
||||||
gboolean result;
|
gboolean result;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
GstStructure *s;
|
|
||||||
|
|
||||||
if (self->caps_width == self->negotiated_width &&
|
if (!gst_pad_check_reconfigure (self->srcpad))
|
||||||
self->caps_height == self->negotiated_height &&
|
|
||||||
self->caps_fps_n == self->negotiated_fps_n &&
|
|
||||||
self->caps_fps_d == self->negotiated_fps_d) {
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
caps = gst_caps_copy (gst_pad_get_pad_template_caps (self->srcpad));
|
caps = gst_video_info_to_caps (&self->vinfo);
|
||||||
s = gst_caps_get_structure (caps, 0);
|
|
||||||
gst_structure_set (s,
|
|
||||||
"width", G_TYPE_INT, self->negotiated_width,
|
|
||||||
"height", G_TYPE_INT, self->negotiated_height,
|
|
||||||
"framerate", GST_TYPE_FRACTION,
|
|
||||||
self->negotiated_fps_n, self->negotiated_fps_d, NULL);
|
|
||||||
result = gst_pad_set_caps (self->srcpad, caps);
|
result = gst_pad_set_caps (self->srcpad, caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
self->caps_width = self->negotiated_width;
|
|
||||||
self->caps_height = self->negotiated_height;
|
|
||||||
self->caps_fps_n = self->negotiated_fps_n;
|
|
||||||
self->caps_fps_d = self->negotiated_fps_d;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_vtdec_chain (GstPad * pad, GstBuffer * buf)
|
gst_vtdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstVTDec *self = GST_VTDEC_CAST (GST_PAD_PARENT (pad));
|
GstVTDec *self = GST_VTDEC_CAST (parent);
|
||||||
|
|
||||||
if (!gst_vtdec_is_negotiated (self))
|
if (!gst_vtdec_is_negotiated (self))
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
if (self->session == NULL || self->negotiated_width < 0)
|
if (self->session == NULL)
|
||||||
goto pending_caps;
|
goto pending_caps;
|
||||||
|
|
||||||
return gst_vtdec_decode_buffer (self, buf);
|
return gst_vtdec_decode_buffer (self, buf);
|
||||||
|
@ -311,7 +339,7 @@ gst_vtdec_create_format_description (GstVTDec * self)
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
|
|
||||||
status = self->ctx->cm->CMVideoFormatDescriptionCreate (NULL,
|
status = self->ctx->cm->CMVideoFormatDescriptionCreate (NULL,
|
||||||
self->details->format_id, self->negotiated_width, self->negotiated_height,
|
self->details->format_id, self->vinfo.width, self->vinfo.height,
|
||||||
NULL, &fmt_desc);
|
NULL, &fmt_desc);
|
||||||
if (status == noErr)
|
if (status == noErr)
|
||||||
return fmt_desc;
|
return fmt_desc;
|
||||||
|
@ -325,13 +353,18 @@ gst_vtdec_create_format_description_from_codec_data (GstVTDec * self,
|
||||||
{
|
{
|
||||||
CMFormatDescriptionRef fmt_desc;
|
CMFormatDescriptionRef fmt_desc;
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
|
gst_buffer_map (codec_data, &map, GST_MAP_READ);
|
||||||
|
|
||||||
status =
|
status =
|
||||||
self->ctx->cm->
|
self->ctx->cm->
|
||||||
FigVideoFormatDescriptionCreateWithSampleDescriptionExtensionAtom (NULL,
|
FigVideoFormatDescriptionCreateWithSampleDescriptionExtensionAtom (NULL,
|
||||||
self->details->format_id, self->negotiated_width, self->negotiated_height,
|
self->details->format_id, self->vinfo.width, self->vinfo.height,
|
||||||
'avcC', GST_BUFFER_DATA (codec_data), GST_BUFFER_SIZE (codec_data),
|
'avcC', map.data, map.size, NULL, &fmt_desc);
|
||||||
&fmt_desc);
|
|
||||||
|
gst_buffer_unmap (codec_data, &map);
|
||||||
|
|
||||||
if (status == noErr)
|
if (status == noErr)
|
||||||
return fmt_desc;
|
return fmt_desc;
|
||||||
else
|
else
|
||||||
|
@ -352,11 +385,11 @@ gst_vtdec_create_session (GstVTDec * self, CMFormatDescriptionRef fmt_desc)
|
||||||
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferPixelFormatTypeKey),
|
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferPixelFormatTypeKey),
|
||||||
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange);
|
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange);
|
||||||
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferWidthKey),
|
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferWidthKey),
|
||||||
self->negotiated_width);
|
self->vinfo.width);
|
||||||
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey),
|
gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey),
|
||||||
self->negotiated_height);
|
self->vinfo.height);
|
||||||
gst_vtutil_dict_set_i32 (pb_attrs,
|
gst_vtutil_dict_set_i32 (pb_attrs,
|
||||||
*(cv->kCVPixelBufferBytesPerRowAlignmentKey), 2 * self->negotiated_width);
|
*(cv->kCVPixelBufferBytesPerRowAlignmentKey), 2 * self->vinfo.width);
|
||||||
|
|
||||||
callback.func = gst_vtdec_enqueue_frame;
|
callback.func = gst_vtdec_enqueue_frame;
|
||||||
callback.data = self;
|
callback.data = self;
|
||||||
|
@ -364,7 +397,7 @@ gst_vtdec_create_session (GstVTDec * self, CMFormatDescriptionRef fmt_desc)
|
||||||
status = self->ctx->vt->VTDecompressionSessionCreate (NULL, fmt_desc,
|
status = self->ctx->vt->VTDecompressionSessionCreate (NULL, fmt_desc,
|
||||||
NULL, pb_attrs, &callback, &session);
|
NULL, pb_attrs, &callback, &session);
|
||||||
GST_INFO_OBJECT (self, "VTDecompressionSessionCreate for %d x %d => %d",
|
GST_INFO_OBJECT (self, "VTDecompressionSessionCreate for %d x %d => %d",
|
||||||
self->negotiated_width, self->negotiated_height, status);
|
self->vinfo.width, self->vinfo.height, status);
|
||||||
|
|
||||||
CFRelease (pb_attrs);
|
CFRelease (pb_attrs);
|
||||||
|
|
||||||
|
@ -416,7 +449,6 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf)
|
||||||
GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i);
|
GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i);
|
||||||
|
|
||||||
if (ret == GST_FLOW_OK) {
|
if (ret == GST_FLOW_OK) {
|
||||||
gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad));
|
|
||||||
ret = gst_pad_push (self->srcpad, buf);
|
ret = gst_pad_push (self->srcpad, buf);
|
||||||
} else {
|
} else {
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
|
@ -437,9 +469,8 @@ gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2,
|
||||||
if (result != kVTSuccess)
|
if (result != kVTSuccess)
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
buf = gst_core_video_buffer_new (self->ctx, cvbuf);
|
buf = gst_core_video_buffer_new (self->ctx, cvbuf, &self->vinfo);
|
||||||
gst_buffer_copy_metadata (buf, self->cur_inbuf,
|
gst_buffer_copy_into (buf, self->cur_inbuf, GST_BUFFER_COPY_METADATA, 0, -1);
|
||||||
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
|
|
||||||
|
|
||||||
g_ptr_array_add (self->cur_outbufs, buf);
|
g_ptr_array_add (self->cur_outbufs, buf);
|
||||||
|
|
||||||
|
@ -454,23 +485,33 @@ gst_vtdec_sample_buffer_from (GstVTDec * self, GstBuffer * buf)
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
CMBlockBufferRef bbuf = NULL;
|
CMBlockBufferRef bbuf = NULL;
|
||||||
CMSampleBufferRef sbuf = NULL;
|
CMSampleBufferRef sbuf = NULL;
|
||||||
|
GstMapInfo map;
|
||||||
|
|
||||||
g_assert (self->fmt_desc != NULL);
|
g_assert (self->fmt_desc != NULL);
|
||||||
|
|
||||||
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
|
|
||||||
status = cm->CMBlockBufferCreateWithMemoryBlock (NULL,
|
status = cm->CMBlockBufferCreateWithMemoryBlock (NULL,
|
||||||
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), kCFAllocatorNull, NULL,
|
map.data, (gint64) map.size, kCFAllocatorNull, NULL, 0, (gint64) map.size,
|
||||||
0, GST_BUFFER_SIZE (buf), FALSE, &bbuf);
|
FALSE, &bbuf);
|
||||||
|
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
if (status != noErr)
|
if (status != noErr)
|
||||||
goto beach;
|
goto error;
|
||||||
|
|
||||||
status = cm->CMSampleBufferCreate (NULL, bbuf, TRUE, 0, 0, self->fmt_desc,
|
status = cm->CMSampleBufferCreate (NULL, bbuf, TRUE, 0, 0, self->fmt_desc,
|
||||||
1, 0, NULL, 0, NULL, &sbuf);
|
1, 0, NULL, 0, NULL, &sbuf);
|
||||||
if (status != noErr)
|
if (status != noErr)
|
||||||
goto beach;
|
goto error;
|
||||||
|
|
||||||
beach:
|
beach:
|
||||||
cm->FigBlockBufferRelease (bbuf);
|
cm->FigBlockBufferRelease (bbuf);
|
||||||
return sbuf;
|
return sbuf;
|
||||||
|
|
||||||
|
error:
|
||||||
|
GST_ERROR_OBJECT (self, "err %d", status);
|
||||||
|
goto beach;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define __GST_VTDEC_H__
|
#define __GST_VTDEC_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
#include "coremediactx.h"
|
#include "coremediactx.h"
|
||||||
|
|
||||||
|
@ -62,10 +63,7 @@ struct _GstVTDec
|
||||||
|
|
||||||
GstCoreMediaCtx * ctx;
|
GstCoreMediaCtx * ctx;
|
||||||
|
|
||||||
gint negotiated_width, negotiated_height;
|
GstVideoInfo vinfo;
|
||||||
gint negotiated_fps_n, negotiated_fps_d;
|
|
||||||
gint caps_width, caps_height;
|
|
||||||
gint caps_fps_n, caps_fps_d;
|
|
||||||
CMFormatDescriptionRef fmt_desc;
|
CMFormatDescriptionRef fmt_desc;
|
||||||
VTDecompressionSessionRef session;
|
VTDecompressionSessionRef session;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue