From a7ae20305aa6d67e589fe2b0bb7ca109faa11bc0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 23 Jul 2012 11:36:01 +0200 Subject: [PATCH] schro: Add support for video metadata and arbitrary strides --- ext/schroedinger/gstschrodec.c | 34 +++++++++++++++-- ext/schroedinger/gstschroenc.c | 19 ++++++++-- ext/schroedinger/gstschroutils.c | 79 ++++++++++++++++++++++++++++------------ ext/schroedinger/gstschroutils.h | 3 +- 4 files changed, 102 insertions(+), 33 deletions(-) diff --git a/ext/schroedinger/gstschrodec.c b/ext/schroedinger/gstschrodec.c index ced4601..0e93b73 100644 --- a/ext/schroedinger/gstschrodec.c +++ b/ext/schroedinger/gstschrodec.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -89,6 +91,8 @@ static GstFlowReturn gst_schro_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame); static gboolean gst_schro_dec_finish (GstVideoDecoder * base_video_decoder); static void gst_schrodec_send_tags (GstSchroDec * schro_dec); +static gboolean gst_schro_dec_decide_allocation (GstVideoDecoder * decoder, + GstQuery * query); static GstStaticPadTemplate gst_schro_dec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -136,6 +140,8 @@ gst_schro_dec_class_init (GstSchroDecClass * klass) base_video_decoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_schro_dec_handle_frame); base_video_decoder_class->finish = GST_DEBUG_FUNCPTR (gst_schro_dec_finish); + base_video_decoder_class->decide_allocation = + GST_DEBUG_FUNCPTR (gst_schro_dec_decide_allocation); } static void @@ -457,10 +463,7 @@ gst_schro_dec_process (GstSchroDec * schro_dec, gboolean eos) outbuf = gst_video_decoder_allocate_output_buffer (GST_VIDEO_DECODER (schro_dec)); - schro_frame = - gst_schro_buffer_wrap (outbuf, TRUE, - GST_VIDEO_INFO_FORMAT (&state->info), state->info.width, - state->info.height); + schro_frame = gst_schro_buffer_wrap (outbuf, TRUE, &state->info); schro_decoder_add_output_picture (schro_dec->decoder, schro_frame); gst_video_codec_state_unref (state); break; @@ -552,3 +555,26 @@ gst_schro_dec_finish (GstVideoDecoder * base_video_decoder) return gst_schro_dec_process (schro_dec, TRUE); } + +static gboolean +gst_schro_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query) +{ + GstBufferPool *pool; + GstStructure *config; + + if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (decoder, + query)) + return FALSE; + + gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL); + + config = gst_buffer_pool_get_config (pool); + if (gst_query_find_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL)) { + gst_buffer_pool_config_add_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_META); + } + + gst_object_unref (pool); + + return TRUE; +} diff --git a/ext/schroedinger/gstschroenc.c b/ext/schroedinger/gstschroenc.c index 0affaa2..3b9118c 100644 --- a/ext/schroedinger/gstschroenc.c +++ b/ext/schroedinger/gstschroenc.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -104,6 +105,8 @@ static GstFlowReturn gst_schro_enc_handle_frame (GstVideoEncoder * static GstFlowReturn gst_schro_enc_pre_push (GstVideoEncoder * base_video_encoder, GstVideoCodecFrame * frame); static void gst_schro_enc_finalize (GObject * object); +static gboolean gst_schro_enc_propose_allocation (GstVideoEncoder * encoder, + GstQuery * query); static GstStaticPadTemplate gst_schro_enc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -214,6 +217,8 @@ gst_schro_enc_class_init (GstSchroEncClass * klass) basevideocoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_schro_enc_handle_frame); basevideocoder_class->pre_push = GST_DEBUG_FUNCPTR (gst_schro_enc_pre_push); + basevideocoder_class->propose_allocation = + GST_DEBUG_FUNCPTR (gst_schro_enc_propose_allocation); } static void @@ -525,9 +530,7 @@ gst_schro_enc_handle_frame (GstVideoEncoder * base_video_encoder, /* FIXME : We could make that method just take GstVideoInfo ... */ schro_frame = gst_schro_buffer_wrap (gst_buffer_ref (frame->input_buffer), - FALSE, - GST_VIDEO_INFO_FORMAT (info), - GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info)); + FALSE, info); GST_DEBUG ("pushing frame %p", frame); schro_encoder_push_frame_full (schro_enc->encoder, schro_frame, frame); @@ -580,6 +583,16 @@ gst_schro_enc_pre_push (GstVideoEncoder * base_video_encoder, return GST_FLOW_OK; } +static gboolean +gst_schro_enc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query) +{ + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); + + return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder, + query); +} + + static GstFlowReturn gst_schro_enc_process (GstSchroEnc * schro_enc) { diff --git a/ext/schroedinger/gstschroutils.c b/ext/schroedinger/gstschroutils.c index 3279209..db9ff3b 100644 --- a/ext/schroedinger/gstschroutils.c +++ b/ext/schroedinger/gstschroutils.c @@ -38,8 +38,7 @@ GST_DEBUG_CATEGORY_EXTERN (schro_debug); typedef struct { - GstBuffer *buf; - GstMapInfo info; + GstVideoFrame frame; } FrameData; @@ -48,8 +47,7 @@ gst_schro_frame_free (SchroFrame * frame, void *priv) { FrameData *data = priv; - gst_buffer_unmap (data->buf, &data->info); - gst_buffer_unref (data->buf); + gst_video_frame_unmap (&data->frame); g_slice_free (FrameData, data); } @@ -58,58 +56,62 @@ GstBuffer * gst_schro_frame_get_buffer (SchroFrame * frame) { if (frame->priv) - return gst_buffer_ref (((FrameData *) frame->priv)->buf); + return gst_buffer_ref (((FrameData *) frame->priv)->frame.buffer); return NULL; } SchroFrame * -gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoFormat format, - int width, int height) +gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoInfo * vinfo) { SchroFrame *frame; - GstMapInfo info; + GstVideoFrame vframe; FrameData *data; + gint i; - if (!gst_buffer_map (buf, &info, (write ? GST_MAP_READWRITE : GST_MAP_READ))) + if (!gst_video_frame_map (&vframe, vinfo, buf, + (write ? GST_MAP_READWRITE : GST_MAP_READ))) return NULL; - switch (format) { + frame = schro_frame_new (); + + frame->width = GST_VIDEO_FRAME_WIDTH (&vframe); + frame->height = GST_VIDEO_FRAME_HEIGHT (&vframe); + + switch (GST_VIDEO_FRAME_FORMAT (&vframe)) { case GST_VIDEO_FORMAT_I420: - frame = schro_frame_new_from_data_I420 (info.data, width, height); - break; case GST_VIDEO_FORMAT_YV12: - frame = schro_frame_new_from_data_YV12 (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_U8_420; break; case GST_VIDEO_FORMAT_YUY2: - frame = schro_frame_new_from_data_YUY2 (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_YUYV; break; case GST_VIDEO_FORMAT_UYVY: - frame = schro_frame_new_from_data_UYVY (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_UYVY; break; case GST_VIDEO_FORMAT_AYUV: - frame = schro_frame_new_from_data_AYUV (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_AYUV; break; #if SCHRO_CHECK_VERSION(1,0,12) case GST_VIDEO_FORMAT_ARGB: - frame = schro_frame_new_from_data_ARGB (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_ARGB; break; #endif #if SCHRO_CHECK_VERSION(1,0,11) case GST_VIDEO_FORMAT_Y42B: - frame = schro_frame_new_from_data_Y42B (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_U8_422; break; case GST_VIDEO_FORMAT_Y444: - frame = schro_frame_new_from_data_Y444 (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_U8_444; break; case GST_VIDEO_FORMAT_v210: - frame = schro_frame_new_from_data_v210 (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_v210; break; case GST_VIDEO_FORMAT_v216: - frame = schro_frame_new_from_data_v216 (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_v216; break; case GST_VIDEO_FORMAT_AYUV64: - frame = schro_frame_new_from_data_AY64 (info.data, width, height); + frame->format = SCHRO_FRAME_FORMAT_AY64; break; #endif default: @@ -117,9 +119,38 @@ gst_schro_buffer_wrap (GstBuffer * buf, gboolean write, GstVideoFormat format, return NULL; } + if (SCHRO_FRAME_IS_PACKED (frame->format)) { + frame->components[0].format = frame->format; + frame->components[0].width = frame->width; + frame->components[0].height = frame->height; + frame->components[0].stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0); + frame->components[0].length = frame->components[0].stride * frame->height; + frame->components[0].data = vframe.data[0]; + frame->components[0].v_shift = 0; + frame->components[0].h_shift = 0; + } else { + for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (&vframe); i++) { + frame->components[i].format = frame->format; + frame->components[i].width = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, i); + frame->components[i].height = GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, i); + frame->components[i].stride = GST_VIDEO_FRAME_COMP_STRIDE (&vframe, i); + frame->components[i].length = + frame->components[i].stride * frame->components[i].height; + frame->components[i].data = GST_VIDEO_FRAME_COMP_DATA (&vframe, i); + if (i == 0) { + frame->components[i].v_shift = 0; + frame->components[i].h_shift = 0; + } else { + frame->components[i].v_shift = + SCHRO_FRAME_FORMAT_H_SHIFT (frame->format); + frame->components[i].h_shift = + SCHRO_FRAME_FORMAT_H_SHIFT (frame->format); + } + } + } + data = g_slice_new0 (FrameData); - data->buf = buf; - data->info = info; + data->frame = vframe; schro_frame_set_free_callback (frame, gst_schro_frame_free, data); return frame; diff --git a/ext/schroedinger/gstschroutils.h b/ext/schroedinger/gstschroutils.h index 705dd8c..bdc41b6 100644 --- a/ext/schroedinger/gstschroutils.h +++ b/ext/schroedinger/gstschroutils.h @@ -35,8 +35,7 @@ #endif SchroFrame * -gst_schro_buffer_wrap (GstBuffer *buf, gboolean write, GstVideoFormat format, int width, - int height); +gst_schro_buffer_wrap (GstBuffer *buf, gboolean write, GstVideoInfo * vinfo); GstBuffer * gst_schro_frame_get_buffer (SchroFrame * frame); GstBuffer * gst_schro_wrap_schro_buffer (SchroBuffer *buffer); -- 2.7.4