diff --git a/ext/schroedinger/gstschrodec.c b/ext/schroedinger/gstschrodec.c index a58daa5899..1ebe47b4ac 100644 --- a/ext/schroedinger/gstschrodec.c +++ b/ext/schroedinger/gstschrodec.c @@ -79,8 +79,6 @@ enum static void gst_schro_dec_finalize (GObject * object); -static gboolean gst_schro_dec_sink_query (GstPad * pad, GstQuery * query); - static gboolean gst_schro_dec_start (GstVideoDecoder * dec); static gboolean gst_schro_dec_stop (GstVideoDecoder * dec); static gboolean gst_schro_dec_reset (GstVideoDecoder * dec, gboolean hard); @@ -100,43 +98,37 @@ GST_STATIC_PAD_TEMPLATE ("sink", ); static GstStaticPadTemplate gst_schro_dec_src_template = - GST_STATIC_PAD_TEMPLATE ("src", +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV (GST_SCHRO_YUV_LIST) ";" - GST_VIDEO_CAPS_ARGB) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_SCHRO_YUV_LIST)) ); -GST_BOILERPLATE (GstSchroDec, gst_schro_dec, GstVideoDecoder, - GST_TYPE_VIDEO_DECODER); - -static void -gst_schro_dec_base_init (gpointer g_class) -{ - - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_static_pad_template (element_class, - &gst_schro_dec_src_template); - gst_element_class_add_static_pad_template (element_class, - &gst_schro_dec_sink_template); - - gst_element_class_set_details_simple (element_class, "Dirac Decoder", - "Codec/Decoder/Video", - "Decode Dirac streams", "David Schleef "); -} +#define parent_class gst_schro_dec_parent_class +G_DEFINE_TYPE (GstSchroDec, gst_schro_dec, GST_TYPE_VIDEO_DECODER); static void gst_schro_dec_class_init (GstSchroDecClass * klass) { GObjectClass *gobject_class; + GstElementClass *element_class; GstVideoDecoderClass *base_video_decoder_class; gobject_class = G_OBJECT_CLASS (klass); + element_class = GST_ELEMENT_CLASS (klass); base_video_decoder_class = GST_VIDEO_DECODER_CLASS (klass); gobject_class->finalize = gst_schro_dec_finalize; + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_schro_dec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_schro_dec_sink_template)); + + gst_element_class_set_details_simple (element_class, "Dirac Decoder", + "Codec/Decoder/Video", + "Decode Dirac streams", "David Schleef "); + base_video_decoder_class->start = GST_DEBUG_FUNCPTR (gst_schro_dec_start); base_video_decoder_class->stop = GST_DEBUG_FUNCPTR (gst_schro_dec_stop); base_video_decoder_class->reset = GST_DEBUG_FUNCPTR (gst_schro_dec_reset); @@ -147,110 +139,12 @@ gst_schro_dec_class_init (GstSchroDecClass * klass) } static void -gst_schro_dec_init (GstSchroDec * schro_dec, GstSchroDecClass * klass) +gst_schro_dec_init (GstSchroDec * schro_dec) { GST_DEBUG ("gst_schro_dec_init"); - gst_pad_set_query_function (GST_VIDEO_DECODER_SINK_PAD (schro_dec), - gst_schro_dec_sink_query); - schro_dec->decoder = schro_decoder_new (); - gst_video_decoder_set_packetized (schro_dec, FALSE); -} - -#define OGG_DIRAC_GRANULE_SHIFT 22 -#define OGG_DIRAC_GRANULE_LOW_MASK ((1ULL<> 22) + (granulepos & OGG_DIRAC_GRANULE_LOW_MASK)) >> 9; - /* dist_h = (granulepos >> 22) & 0xff; - * dist_l = granulepos & 0xff; - * dist = (dist_h << 8) | dist_l; - * delay = (granulepos >> 9) & 0x1fff; - * dt = pt - delay; */ - - return pt >> 1; -} - -static gboolean -gst_schro_dec_sink_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = FALSE; - GstSchroDec *dec; - GstVideoCodecState *state; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - if (src_format != GST_FORMAT_DEFAULT || *dest_format != GST_FORMAT_TIME) - return FALSE; - - dec = GST_SCHRO_DEC (gst_pad_get_parent (pad)); - - /* FIXME: check if we are in a decoding state */ - - state = gst_video_decoder_get_output_state (GST_VIDEO_DECODER (dec)); - - if (G_UNLIKELY (state == NULL)) - goto beach; - - if (state->info.fps_d == 0) - goto beach; - - *dest_value = gst_util_uint64_scale (granulepos_to_frame (src_value), - state->info.fps_d * GST_SECOND, state->info.fps_n); - res = TRUE; - -beach: - gst_object_unref (dec); - - return res; -} - -static gboolean -gst_schro_dec_sink_query (GstPad * pad, GstQuery * query) -{ - GstSchroDec *dec; - gboolean res = FALSE; - - dec = GST_SCHRO_DEC (gst_pad_get_parent (pad)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = gst_schro_dec_sink_convert (pad, src_fmt, src_val, &dest_fmt, - &dest_val); - if (!res) - goto error; - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - break; - } - default: - res = gst_pad_query_default (pad, query); - break; - } -done: - gst_object_unref (dec); - - return res; -error: - GST_DEBUG_OBJECT (dec, "query failed"); - goto done; + gst_video_decoder_set_packetized (GST_VIDEO_DECODER (schro_dec), FALSE); } static gboolean @@ -520,12 +414,12 @@ gst_schrodec_send_tags (GstSchroDec * schro_dec) { GstTagList *list; - list = gst_tag_list_new (); + list = gst_tag_list_new_empty (); gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_VIDEO_CODEC, "Dirac", NULL); - gst_element_found_tags_for_pad (GST_ELEMENT_CAST (schro_dec), - GST_VIDEO_DECODER_SRC_PAD (schro_dec), list); + gst_pad_push_event (GST_VIDEO_DECODER_SRC_PAD (schro_dec), + gst_event_new_tag (list)); } static GstFlowReturn @@ -581,12 +475,9 @@ gst_schro_dec_process (GstSchroDec * schro_dec, gboolean eos) frame = tag->value; if (schro_frame) { - if (schro_frame->priv) { + if ((frame->output_buffer = gst_schro_frame_get_buffer (schro_frame))) { GstFlowReturn flow_ret; - frame->output_buffer = - gst_buffer_ref (GST_BUFFER (schro_frame->priv)); - flow_ret = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (schro_dec), frame); diff --git a/ext/schroedinger/gstschroenc.c b/ext/schroedinger/gstschroenc.c index 334bf93f10..cdab5ab986 100644 --- a/ext/schroedinger/gstschroenc.c +++ b/ext/schroedinger/gstschroenc.c @@ -105,16 +105,11 @@ static GstFlowReturn gst_schro_enc_pre_push (GstVideoEncoder * base_video_encoder, GstVideoCodecFrame * frame); static void gst_schro_enc_finalize (GObject * object); -#if SCHRO_CHECK_VERSION(1,0,12) -#define ARGB_CAPS ";" GST_VIDEO_CAPS_ARGB -#else -#define ARGB_CAPS -#endif static GstStaticPadTemplate gst_schro_enc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV (GST_SCHRO_YUV_LIST) ARGB_CAPS) + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_SCHRO_YUV_LIST)) ); static GstStaticPadTemplate gst_schro_enc_src_template = @@ -124,24 +119,8 @@ static GstStaticPadTemplate gst_schro_enc_src_template = GST_STATIC_CAPS ("video/x-dirac;video/x-qt-part;video/x-mp4-part") ); -GST_BOILERPLATE (GstSchroEnc, gst_schro_enc, GstVideoEncoder, - GST_TYPE_VIDEO_ENCODER); - -static void -gst_schro_enc_base_init (gpointer g_class) -{ - - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_static_pad_template (element_class, - &gst_schro_enc_src_template); - gst_element_class_add_static_pad_template (element_class, - &gst_schro_enc_sink_template); - - gst_element_class_set_details_simple (element_class, "Dirac Encoder", - "Codec/Encoder/Video", - "Encode raw video into Dirac stream", "David Schleef "); -} +#define parent_class gst_schro_enc_parent_class +G_DEFINE_TYPE (GstSchroEnc, gst_schro_enc, GST_TYPE_VIDEO_ENCODER); static GType register_enum_list (const SchroEncoderSetting * setting) @@ -172,10 +151,12 @@ static void gst_schro_enc_class_init (GstSchroEncClass * klass) { GObjectClass *gobject_class; + GstElementClass *element_class; GstVideoEncoderClass *basevideocoder_class; int i; gobject_class = G_OBJECT_CLASS (klass); + element_class = GST_ELEMENT_CLASS (klass); basevideocoder_class = GST_VIDEO_ENCODER_CLASS (klass); gobject_class->set_property = gst_schro_enc_set_property; @@ -216,6 +197,15 @@ gst_schro_enc_class_init (GstSchroEncClass * klass) } } + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_schro_enc_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_schro_enc_sink_template)); + + gst_element_class_set_details_simple (element_class, "Dirac Encoder", + "Codec/Encoder/Video", + "Encode raw video into Dirac stream", "David Schleef "); + basevideocoder_class->set_format = GST_DEBUG_FUNCPTR (gst_schro_enc_set_format); basevideocoder_class->start = GST_DEBUG_FUNCPTR (gst_schro_enc_start); @@ -227,7 +217,7 @@ gst_schro_enc_class_init (GstSchroEncClass * klass) } static void -gst_schro_enc_init (GstSchroEnc * schro_enc, GstSchroEncClass * klass) +gst_schro_enc_init (GstSchroEnc * schro_enc) { GST_DEBUG ("gst_schro_enc_init"); @@ -364,32 +354,43 @@ gst_schro_enc_set_format (GstVideoEncoder * base_video_encoder, output_state = gst_video_encoder_set_output_state (base_video_encoder, - gst_caps_new_simple ("video/x-dirac", NULL), state); + gst_caps_new_empty_simple ("video/x-dirac"), state); - GST_BUFFER_FLAG_SET (seq_header_buffer, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_FLAG_SET (seq_header_buffer, GST_BUFFER_FLAG_HEADER); { GValue array = { 0 }; GValue value = { 0 }; + guint8 *outdata; GstBuffer *buf; - int size; + GstMemory *seq_header_memory, *extra_header; + gsize size; g_value_init (&array, GST_TYPE_ARRAY); g_value_init (&value, GST_TYPE_BUFFER); - size = GST_BUFFER_SIZE (seq_header_buffer); - buf = gst_buffer_new_and_alloc (size + SCHRO_PARSE_HEADER_SIZE); + + buf = gst_buffer_new (); + /* Add the sequence header */ + seq_header_memory = gst_buffer_get_memory (seq_header_buffer, 0); + gst_buffer_append_memory (buf, seq_header_memory); + + size = gst_buffer_get_size (buf) + SCHRO_PARSE_HEADER_SIZE; + outdata = g_malloc0 (SCHRO_PARSE_HEADER_SIZE); + + GST_WRITE_UINT32_BE (outdata, 0x42424344); + GST_WRITE_UINT8 (outdata + 4, SCHRO_PARSE_CODE_END_OF_SEQUENCE); + GST_WRITE_UINT32_BE (outdata + 5, 0); + GST_WRITE_UINT32_BE (outdata + 9, size); + + extra_header = gst_memory_new_wrapped (0, outdata, SCHRO_PARSE_HEADER_SIZE, + 0, SCHRO_PARSE_HEADER_SIZE, outdata, g_free); + gst_buffer_append_memory (buf, extra_header); /* ogg(mux) expects the header buffers to have 0 timestamps - set OFFSET and OFFSET_END accordingly */ GST_BUFFER_OFFSET (buf) = 0; GST_BUFFER_OFFSET_END (buf) = 0; - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_HEADER); - memcpy (GST_BUFFER_DATA (buf), GST_BUFFER_DATA (seq_header_buffer), size); - GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 0, 0x42424344); - GST_WRITE_UINT8 (GST_BUFFER_DATA (buf) + size + 4, - SCHRO_PARSE_CODE_END_OF_SEQUENCE); - GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 5, 0); - GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 9, size); gst_value_set_buffer (&value, buf); gst_buffer_unref (buf); gst_value_array_append_value (&array, &value); @@ -610,10 +611,12 @@ gst_schro_enc_process (GstSchroEnc * schro_enc) GstMessage *message; GstStructure *structure; GstBuffer *buf; + gpointer data; - buf = gst_buffer_new_and_alloc (sizeof (double) * 21); + data = g_malloc (sizeof (double) * 21); schro_encoder_get_frame_stats (schro_enc->encoder, - (double *) GST_BUFFER_DATA (buf), 21); + (double *) data, 21); + buf = gst_buffer_new_wrapped (data, sizeof (double) * 21); structure = gst_structure_new ("GstSchroEnc", "frame-stats", GST_TYPE_BUFFER, buf, NULL); gst_buffer_unref (buf); diff --git a/ext/schroedinger/gstschroutils.c b/ext/schroedinger/gstschroutils.c index f23abf7e54..c08a8ff681 100644 --- a/ext/schroedinger/gstschroutils.c +++ b/ext/schroedinger/gstschroutils.c @@ -36,13 +36,31 @@ GST_DEBUG_CATEGORY_EXTERN (schro_debug); #define GST_CAT_DEFAULT schro_debug - +typedef struct +{ + GstBuffer *buf; + GstMapInfo info; +} FrameData; static void gst_schro_frame_free (SchroFrame * frame, void *priv) { - gst_buffer_unref (GST_BUFFER (priv)); + FrameData *data = priv; + + gst_buffer_unmap (data->buf, &data->info); + gst_buffer_unref (data->buf); + + g_slice_free (FrameData, data); +} + +GstBuffer * +gst_schro_frame_get_buffer (SchroFrame * frame) +{ + if (frame->priv) + return gst_buffer_ref (((FrameData *) frame->priv)->buf); + + return NULL; } SchroFrame * @@ -50,66 +68,63 @@ gst_schro_buffer_wrap (GstBuffer * buf, GstVideoFormat format, int width, int height) { SchroFrame *frame; + GstMapInfo info; + FrameData *data; + + if (!gst_buffer_map (buf, &info, GST_MAP_READ)) + return NULL; switch (format) { case GST_VIDEO_FORMAT_I420: - frame = - schro_frame_new_from_data_I420 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_I420 (info.data, width, height); break; case GST_VIDEO_FORMAT_YV12: - frame = - schro_frame_new_from_data_YV12 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_YV12 (info.data, width, height); break; case GST_VIDEO_FORMAT_YUY2: - frame = - schro_frame_new_from_data_YUY2 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_YUY2 (info.data, width, height); break; case GST_VIDEO_FORMAT_UYVY: - frame = - schro_frame_new_from_data_UYVY (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_UYVY (info.data, width, height); break; case GST_VIDEO_FORMAT_AYUV: - frame = - schro_frame_new_from_data_AYUV (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_AYUV (info.data, width, height); break; #if SCHRO_CHECK_VERSION(1,0,12) case GST_VIDEO_FORMAT_ARGB: - frame = - schro_frame_new_from_data_ARGB (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_ARGB (info.data, width, height); break; #endif #if SCHRO_CHECK_VERSION(1,0,11) case GST_VIDEO_FORMAT_Y42B: - frame = - schro_frame_new_from_data_Y42B (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_Y42B (info.data, width, height); break; case GST_VIDEO_FORMAT_Y444: - frame = - schro_frame_new_from_data_Y444 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_Y444 (info.data, width, height); break; case GST_VIDEO_FORMAT_v210: - frame = - schro_frame_new_from_data_v210 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_v210 (info.data, width, height); break; case GST_VIDEO_FORMAT_v216: - frame = - schro_frame_new_from_data_v216 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_v216 (info.data, width, height); break; case GST_VIDEO_FORMAT_AYUV64: - frame = - schro_frame_new_from_data_AY64 (GST_BUFFER_DATA (buf), width, height); + frame = schro_frame_new_from_data_AY64 (info.data, width, height); break; #endif default: g_assert_not_reached (); return NULL; } - schro_frame_set_free_callback (frame, gst_schro_frame_free, buf); + + data = g_slice_new0 (FrameData); + data->buf = buf; + data->info = info; + schro_frame_set_free_callback (frame, gst_schro_frame_free, data); return frame; } -#ifdef GST_BUFFER_FREE_FUNC static void schro_buf_free_func (gpointer priv) { @@ -117,43 +132,62 @@ schro_buf_free_func (gpointer priv) schro_buffer_unref (buffer); } -#endif /* takes the reference */ GstBuffer * gst_schro_wrap_schro_buffer (SchroBuffer * buffer) { - GstBuffer *gstbuf; + GstMemory *mem; + GstBuffer *buf; -#ifdef GST_BUFFER_FREE_FUNC - gstbuf = gst_buffer_new (); - GST_BUFFER_DATA (gstbuf) = buffer->data; - GST_BUFFER_SIZE (gstbuf) = buffer->length; - GST_BUFFER_MALLOCDATA (gstbuf) = (void *) buffer; - GST_BUFFER_FREE_FUNC (gstbuf) = schro_buf_free_func; -#else - gstbuf = gst_buffer_new_and_alloc (buffer->length); - memcpy (GST_BUFFER_DATA (gstbuf), buffer->data, buffer->length); -#endif + mem = + gst_memory_new_wrapped (0, buffer->data, buffer->length, 0, + buffer->length, buffer, schro_buf_free_func); + buf = gst_buffer_new (); + gst_buffer_append_memory (buf, mem); - return gstbuf; + return buf; } +typedef struct +{ + GstMemory *mem; + GstMapInfo info; +} BufferData; + static void gst_schro_buffer_free (SchroBuffer * buffer, void *priv) { - gst_buffer_unref (GST_BUFFER (priv)); + BufferData *data = priv; + + gst_memory_unmap (data->mem, &data->info); + gst_memory_unref (data->mem); + g_slice_free (BufferData, priv); } SchroBuffer * gst_schro_wrap_gst_buffer (GstBuffer * buffer) { SchroBuffer *schrobuf; + GstMemory *mem; + GstMapInfo info; + BufferData *data; - schrobuf = schro_buffer_new_with_data (GST_BUFFER_DATA (buffer), - GST_BUFFER_SIZE (buffer)); + mem = gst_buffer_get_all_memory (buffer); + if (!gst_memory_map (mem, &info, GST_MAP_READ)) { + GST_ERROR ("Couldn't get readable memory from gstbuffer"); + return NULL; + } + + /* FIXME : We can't control if data won't be read/write outside + * of schro ... */ + data = g_slice_new0 (BufferData); + data->info = info; + data->mem = mem; + + schrobuf = schro_buffer_new_with_data (info.data, info.size); schrobuf->free = gst_schro_buffer_free; - schrobuf->priv = buffer; + schrobuf->priv = data; return schrobuf; } diff --git a/ext/schroedinger/gstschroutils.h b/ext/schroedinger/gstschroutils.h index c1d06c5038..149ab3e1a1 100644 --- a/ext/schroedinger/gstschroutils.h +++ b/ext/schroedinger/gstschroutils.h @@ -24,15 +24,21 @@ #include #include +#if SCHRO_CHECK_VERSION(1,0,12) +#define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV, Y42B, Y444, v216, v210, AY64, ARGB }" +#else #if SCHRO_CHECK_VERSION(1,0,11) #define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV, Y42B, Y444, v216, v210, AY64 }" #else #define GST_SCHRO_YUV_LIST "{ I420, YV12, YUY2, UYVY, AYUV }" #endif +#endif SchroFrame * gst_schro_buffer_wrap (GstBuffer *buf, GstVideoFormat format, int width, int height); +GstBuffer * gst_schro_frame_get_buffer (SchroFrame * frame); + GstBuffer * gst_schro_wrap_schro_buffer (SchroBuffer *buffer); SchroBuffer * gst_schro_wrap_gst_buffer (GstBuffer *buffer);