diff options
Diffstat (limited to 'omx/gstomxwmvdec.c')
-rw-r--r-- | omx/gstomxwmvdec.c | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/omx/gstomxwmvdec.c b/omx/gstomxwmvdec.c index 64460d9..e21b87b 100644 --- a/omx/gstomxwmvdec.c +++ b/omx/gstomxwmvdec.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd. + * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,6 +36,11 @@ static gboolean gst_omx_wmv_dec_is_format_change (GstOMXVideoDec * dec, static gboolean gst_omx_wmv_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port, GstVideoCodecState * state); +#ifdef USE_OMX_TARGET_TEGRA +static GstFlowReturn gst_omx_wmv_dec_prepare_frame (GstOMXVideoDec * self, + GstVideoCodecFrame * frame); +#endif + enum { PROP_0 @@ -49,6 +55,7 @@ enum G_DEFINE_TYPE_WITH_CODE (GstOMXWMVDec, gst_omx_wmv_dec, GST_TYPE_OMX_VIDEO_DEC, DEBUG_INIT); + static void gst_omx_wmv_dec_class_init (GstOMXWMVDecClass * klass) { @@ -58,8 +65,14 @@ gst_omx_wmv_dec_class_init (GstOMXWMVDecClass * klass) videodec_class->is_format_change = GST_DEBUG_FUNCPTR (gst_omx_wmv_dec_is_format_change); videodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_wmv_dec_set_format); +#ifdef USE_OMX_TARGET_TEGRA + videodec_class->prepare_frame = + GST_DEBUG_FUNCPTR (gst_omx_wmv_dec_prepare_frame); +#endif videodec_class->cdata.default_sink_template_caps = "video/x-wmv, " + "wmvversion= (int) 3, " + "format = (string) {WMV3, WVC1}, " "width=(int) [1,MAX], " "height=(int) [1,MAX]"; gst_element_class_set_static_metadata (element_class, @@ -74,6 +87,7 @@ gst_omx_wmv_dec_class_init (GstOMXWMVDecClass * klass) static void gst_omx_wmv_dec_init (GstOMXWMVDec * self) { + self->wvc1 = FALSE; } static gboolean @@ -90,9 +104,94 @@ gst_omx_wmv_dec_set_format (GstOMXVideoDec * dec, GstOMXPort * port, gboolean ret; OMX_PARAM_PORTDEFINITIONTYPE port_def; +#ifdef USE_OMX_TARGET_TEGRA + GstBuffer *buf; + gint size, width, height, index = 0; + const gchar *format_string; + GstMapInfo read_map = GST_MAP_INFO_INIT; + GstMapInfo write_map = GST_MAP_INFO_INIT; + GstOMXWMVDec *self = GST_OMX_WMV_DEC (dec); + GstCaps *caps = state->caps; + GstStructure *structure = gst_caps_get_structure (caps, 0); + format_string = gst_structure_get_string (structure, "format"); + size = gst_buffer_get_size (state->codec_data); + + if (!strcmp (format_string, "WVC1") || !strcmp (format_string, "wvc1")) { + self->wvc1 = TRUE; + buf = gst_buffer_make_writable (state->codec_data); + /*openmax decoder want first byte to be skipped */ + gst_buffer_resize (buf, 1, -1); + gst_buffer_replace (&state->codec_data, buf); + g_print ("New buffer size = %d\n", gst_buffer_get_size (buf)); + } else if (size > 3) { + gst_buffer_map (state->codec_data, &read_map, GST_MAP_READ); + if (read_map.data[3] != 0xc5) { + //Lets code Annex J and L of the SMPTE VC-1 specification + char seq_l1[] = { 0xff, 0xff, 0xff, 0xc5 }; + char seq_l2[] = { 0x4, 0, 0, 0 }; + char seq_l3[] = { 0xc, 0, 0, 0 }; + + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + + buf = gst_buffer_new_allocate (NULL, size + 32, NULL); + gst_buffer_map (buf, &write_map, GST_MAP_WRITE); + memcpy (write_map.data + index, seq_l1, 4); + index += 4; + memcpy (write_map.data + index, seq_l2, 4); + index += 4; + memcpy (write_map.data + index, read_map.data, 4); + index += 4; + memcpy (write_map.data + index, &height, 4); + index += 4; + memcpy (write_map.data + index, &width, 4); + index += 4; + memcpy (write_map.data + index, seq_l3, 4); + index += 4; + memset (write_map.data + index, 0, 12); + gst_buffer_replace (&state->codec_data, buf); + gst_buffer_unmap (buf, &write_map); + } + gst_buffer_unmap (state->codec_data, &read_map); + } +#endif gst_omx_port_get_port_definition (port, &port_def); port_def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV; ret = gst_omx_port_update_port_definition (port, &port_def) == OMX_ErrorNone; return ret; } + +#ifdef USE_OMX_TARGET_TEGRA +static GstFlowReturn +gst_omx_wmv_dec_prepare_frame (GstOMXVideoDec * dec, GstVideoCodecFrame * frame) +{ + GstOMXWMVDec *self = GST_OMX_WMV_DEC (dec); + GstMemory *mem = NULL; + GstMapInfo read_map = GST_MAP_INFO_INIT; + GstMapInfo write_map = GST_MAP_INFO_INIT; + guint32 start_code; + + if (self->wvc1) { + //Handle WVC1 format + gst_buffer_map (frame->input_buffer, &read_map, GST_MAP_READ); + start_code = + (read_map.data[0] << 24) | (read_map.data[1] << 16) | (read_map. + data[2] << 8) | read_map.data[3]; + gst_buffer_unmap (frame->input_buffer, &read_map); + + if (start_code != 0x10D && start_code != 0x10E) { + mem = gst_allocator_alloc (NULL, 4, NULL); + gst_memory_map (mem, &write_map, GST_MAP_WRITE); + write_map.data[0] = 0; + write_map.data[1] = 0; + write_map.data[2] = 1; + write_map.data[3] = 0xD; + gst_memory_unmap (mem, &write_map); + gst_buffer_prepend_memory (frame->input_buffer, mem); + } + + } + return GST_FLOW_OK; +} +#endif |