diff options
author | harinarayan <harinarayan@24075187-2e39-4e88-bbb8-bc8aa768f540> | 2012-01-19 11:31:01 +0000 |
---|---|---|
committer | harinarayan <harinarayan@24075187-2e39-4e88-bbb8-bc8aa768f540> | 2012-01-19 11:31:01 +0000 |
commit | 197c9239e6d00c2c6649afd84cd6e5a394702b8b (patch) | |
tree | 1e0a9d84fe5e8d1d452323fa2689f08576350f9d | |
parent | 427e41df45c8e79ffa8da6860408fdb91cccdf8c (diff) |
git-svn-id: https://gstreamer.ti.com/svn/gstreamer_ti/trunk@1023 24075187-2e39-4e88-bbb8-bc8aa768f540
62 files changed, 6676 insertions, 500 deletions
diff --git a/gstreamer_ti_dm81xx/Makefile.common b/gstreamer_ti_dm81xx/Makefile.common index 509f5fe..8e9df31 100755 --- a/gstreamer_ti_dm81xx/Makefile.common +++ b/gstreamer_ti_dm81xx/Makefile.common @@ -39,10 +39,10 @@ # # These paths must be specified or the build will fail. #------------------------------------------------------------------------------ -TARGET_ROOT_DIR = /proj/NEE/hari/prashant_gstreamer/target -GSTREAMER_DIR = /opt/gstreamer -GST_TI_PLATFORM = dm814x -EZSDK_INSTALL_DIR = /proj/NEE/hari/ti-ezsdk_dm814x-evm_5_02_01_59 +TARGET_ROOT_DIR = /home2/hari/ti-ezsdk_dm816x-evm_5_03_01_15/rootfs +GSTREAMER_DIR = /usr +GST_TI_PLATFORM = dm816x +EZSDK_INSTALL_DIR = /home2/hari/ti-ezsdk_dm816x-evm_5_03_01_15 #------------------------------------------------------------------------------ # Build configuration: # @@ -365,6 +365,10 @@ CFLAGS_dm816x = -march=armv7-a -mtune=cortex-a8 CFLAGS_dm816x += -mfpu=neon -mfloat-abi=softfp CFLAGS_dm814x = -march=armv7-a -mtune=cortex-a8 CFLAGS_dm814x += -mfpu=neon -mfloat-abi=softfp +ASFLAGS_dm816x = -march=armv7-a -mtune=cortex-a8 +ASFLAGS_dm816x += -mfpu=neon -mfloat-abi=softfp +ASFLAGS_dm814x = -march=armv7-a -mtune=cortex-a8 +ASFLAGS_dm814x += -mfpu=neon -mfloat-abi=softfp LDFLAGS_all = -L$(TARGET_GSTREAMER_DIR)/lib LDFLAGS_dm355 = -L$(LINUXLIBS_INSTALL_DIR)/lib @@ -429,6 +433,7 @@ CC_CONFIGURE_OPTS += NM=$(MVTOOL_PREFIX)nm CC_CONFIGURE_OPTS += RANLIB=$(MVTOOL_PREFIX)ranlib CC_CONFIGURE_OPTS += CPPFLAGS="$(CPPFLAGS_all) $(CPPFLAGS_$(GST_TI_PLATFORM))" CC_CONFIGURE_OPTS += CFLAGS="$(CFLAGS_all) $(CFLAGS_$(GST_TI_PLATFORM))" +CC_CONFIGURE_OPTS += ASFLAGS="$(ASFLAGS_$(GST_TI_PLATFORM))" CC_CONFIGURE_OPTS += LDFLAGS="$(LDFLAGS_all) $(LDFLAGS_$(GST_TI_PLATFORM))" export CC = $(MVTOOL_PREFIX)gcc diff --git a/gstreamer_ti_dm81xx/opensource_build/Makefile b/gstreamer_ti_dm81xx/opensource_build/Makefile index 1822a59..175d445 100644 --- a/gstreamer_ti_dm81xx/opensource_build/Makefile +++ b/gstreamer_ti_dm81xx/opensource_build/Makefile @@ -34,6 +34,7 @@ endif PACKAGES = $(BASE_PACKAGES) $(PLUGIN_PACKAGES) +PATCHFILES = $(foreach x, $(PACKAGES), $(addprefix patchfiles/$(PACKAGE_$(x)_ARCHIVE_BASENAME)/, $(PACKAGE_$(x)_PRECONFIG_PATCHES))) #------------------------------------------------------------------------------ # Build targets #------------------------------------------------------------------------------ @@ -49,25 +50,16 @@ all: .plugins .plugins: .base $(CMD_PREFIX) $(MAKE) plugins $(BUILD_INSTALL) && touch $@ -base: - $(CMD_PREFIX) $(MAKE) orc $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) glib $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) check $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) gstreamer $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) id3tag $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) mad $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) lame $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) faad $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) faac $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) plugins_base $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) ffmpeg $(BUILD_INSTALL) - $(CMD_PREFIX) $(MAKE) plugin_h264 $(BUILD_INSTALL) +base: $(BASE_PACKAGES) plugins: $(PLUGIN_PACKAGES) $(PACKAGES): % : %.build install: +patchfiles.tar.gz: $(PATCHFILES) + $(CMD_PREFIX) tar zcvf patchfiles.tar.gz $(PATCHFILES) + #------------------------------------------------------------------------------ # clean: Remove all build sources #------------------------------------------------------------------------------ diff --git a/gstreamer_ti_dm81xx/opensource_build/Packages.make.dm81xx b/gstreamer_ti_dm81xx/opensource_build/Packages.make.dm81xx index 3f6691d..9224e38 100755 --- a/gstreamer_ti_dm81xx/opensource_build/Packages.make.dm81xx +++ b/gstreamer_ti_dm81xx/opensource_build/Packages.make.dm81xx @@ -15,6 +15,18 @@ # Packages processed by this build script. #------------------------------------------------------------------------------ +#------------------------------------------------------------------------------- +# Package orc +#------------------------------------------------------------------------------- +PACKAGE_orc_BUILD_TARGET = orc +PACKAGE_orc_ARCHIVE_BASENAME = orc-0.4.14 +PACKAGE_orc_PRECONFIG_PATCHES = +PACKAGE_orc_CONFIGURE_OPTS = +PACKAGE_orc_POSTCONFIG_PATCHES = +PACKAGE_orc_DESCRIPTION = \ + ORC compiler +BASE_PACKAGES += $(PACKAGE_orc_BUILD_TARGET) + #------------------------------------------------------------------------------ # Package glib #------------------------------------------------------------------------------ @@ -39,19 +51,6 @@ PACKAGE_check_BUILD_DIRS = PACKAGE_check_DESCRIPTION = Check: a unit test framework for C BASE_PACKAGES += $(PACKAGE_check_BUILD_TARGET) -#------------------------------------------------------------------------------- -# Package orc -#------------------------------------------------------------------------------- -PACKAGE_orc_BUILD_TARGET = orc -PACKAGE_orc_ARCHIVE_BASENAME = orc-0.4.14 -PACKAGE_orc_PRECONFIG_PATCHES = -PACKAGE_orc_CONFIGURE_OPTS = -PACKAGE_orc_POSTCONFIG_PATCHES = -PACKAGE_orc_DESCRIPTION = \ - ORC compiler -PLUGIN_PACKAGES += $(PACKAGE_orc_BUILD_TARGET) - - #------------------------------------------------------------------------------ # Package gstreamer #------------------------------------------------------------------------------ @@ -61,7 +60,8 @@ PACKAGE_gstreamer_PRECONFIG_PATCHES = \ 0001-gst-launch-add-loop-argument.patch \ 0003-add-GstQueryBuffers-query.patch \ 0004-Add-GstEventCrop-event.patch \ - 0005-basetransform-don-t-do-unnecessary-pad_alloc.patch + 0005-basetransform-don-t-do-unnecessary-pad_alloc.patch \ + 0006-queue-free-erroneous-buffer.patch PACKAGE_gstreamer_CONFIGURE_OPTS = --disable-loadsave --disable-tests --disable-examples PACKAGE_gstreamer_POSTCONFIG_PATCHES = PACKAGE_gstreamer_BUILD_DIRS = @@ -122,7 +122,8 @@ PACKAGE_plugins_base_PRECONFIG_PATCHES = \ 0022-stride-support-for-32bit-RGB-formats.patch \ 0023-ffmpegcolorspace-support-for-rowstride.patch \ 0024-discoverer-rowstride-support.patch \ - 0025-playsink-link-omx_colorconv-to-do-HW-accel-color-con.patch + 0025-playsink-link-omx_colorconv-to-do-HW-accel-color-con.patch \ + 0026-playbin-link-omx_scaler-to-do-HW-accel-scale-remove-identity.patch PACKAGE_plugins_base_RUN_AUTOGEN = true PACKAGE_plugins_base_CONFIGURE_OPTS = --disable-examples --disable-x --disable-ogg --disable-vorbis --disable-pango $(ALSA_SUPPORT) PACKAGE_plugins_base_POSTCONFIG_PATCHES = @@ -133,7 +134,7 @@ BASE_PACKAGES += $(PACKAGE_plugins_base_BUILD_TARGET) # Package plugins_good #------------------------------------------------------------------------------ PACKAGE_plugins_good_BUILD_TARGET = plugins_good -PACKAGE_plugins_good_ARCHIVE_BASENAME = gst-plugins-good-0.10.27 +PACKAGE_plugins_good_ARCHIVE_BASENAME = gst-plugins-good-0.10.28 PACKAGE_plugins_good_CONFIGURE_OPTS = --disable-x --disable-shout2 --enable-experimental --disable-aalib --disable-esd PACKAGE_plugins_good_PRECONFIG_PATCHES = \ 0001-v4l2-fix-handling-of-RGB32-BGR32-formats.patch \ @@ -148,7 +149,8 @@ PACKAGE_plugins_good_PRECONFIG_PATCHES = \ 0010-v4l2-prefer-NV12.patch \ 0011-v4l2sink-fix-issue-seen-with-autoconvert.patch \ 0012-v4l2sink-Add-Userptr-support.patch \ - 0013-v4l2sink-interlaced-seq-tb-format.patch + 0013-v4l2sink-interlaced-seq-tb-format.patch \ + 0014-v4l2src-Add-Userptr-support.patch PACKAGE_plugins_good_POSTCONFIG_PATCHES = PACKAGE_plugins_good_DESCRIPTION = \ Select plugins from GStreamer good-plugins (avi, qtdemux, oss, v4l2) @@ -163,10 +165,11 @@ PACKAGE_plugins_bad_PRECONFIG_PATCHES = \ 0001-freeze-Add-timeout-property.patch \ 0002-fixes-to-mux-h264-stream-utilizing-ctts.patch \ 0003-ugly-hack-to-avoid-a-memcpy.patch \ - 0004-h264parse-Add-workaround-for-separate-codec_config-a.patch \ 0005-jpegparse-ignore-unhandled-application-markers.patch \ 0006-mpegvideoparse-merge-sequence-header.patch \ - 0007-h264parse-fix-boundary-condition.patch + 0007-h264parse-fix-boundary-condition.patch \ + 0008-h264parse-modifications-for-playbin.patch \ + 0009-mpeg4videoparse-push-flush-stop-and-new-segment PACKAGE_plugins_bad_POSTCONFIG_PATCHES = PACKAGE_plugins_bad_BUILD_DIRS = PACKAGE_plugins_bad_CONFIGURE_OPTS = --disable-sdl @@ -246,15 +249,3 @@ PACKAGE_plugin_h264_DESCRIPTION = \ Plugin to build nalbytestream_h264 parser PLUGIN_PACKAGES += $(PACKAGE_plugin_h264_BUILD_TARGET) -#------------------------------------------------------------------------------- -# Package orc -#------------------------------------------------------------------------------- -PACKAGE_orc_BUILD_TARGET = orc -PACKAGE_orc_ARCHIVE_BASENAME = orc-0.4.14 -PACKAGE_orc_PRECONFIG_PATCHES = -PACKAGE_orc_CONFIGURE_OPTS = -PACKAGE_orc_POSTCONFIG_PATCHES = -PACKAGE_orc_DESCRIPTION = \ - ORC compiler -PLUGIN_PACKAGES += $(PACKAGE_orc_BUILD_TARGET) - diff --git a/gstreamer_ti_dm81xx/opensource_build/distfiles/gst-plugins-good-0.10.28.tar.gz b/gstreamer_ti_dm81xx/opensource_build/distfiles/gst-plugins-good-0.10.28.tar.gz Binary files differnew file mode 100644 index 0000000..2183303 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/distfiles/gst-plugins-good-0.10.28.tar.gz diff --git a/gstreamer_ti_dm81xx/opensource_build/distfiles/gst-plugins-good-0.10.28.tar.gz.sha256sum b/gstreamer_ti_dm81xx/opensource_build/distfiles/gst-plugins-good-0.10.28.tar.gz.sha256sum new file mode 100644 index 0000000..6fc6195 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/distfiles/gst-plugins-good-0.10.28.tar.gz.sha256sum @@ -0,0 +1 @@ +61a96f9985c362b7d3ce2052f027db5d7228dcde02451471c7c87f28d9993685 gst-plugins-good-0.10.28.tar.gz diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-bad-0.10.21/0008-h264parse-modifications-for-playbin.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-bad-0.10.21/0008-h264parse-modifications-for-playbin.patch new file mode 100644 index 0000000..0a00615 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-bad-0.10.21/0008-h264parse-modifications-for-playbin.patch @@ -0,0 +1,203 @@ +--- gst-plugins-bad-0.10.21.bkp/gst/h264parse/gsth264parse.c 2011-11-28 20:17:08.483609875 +0530 ++++ gst-plugins-bad-0.10.21/gst/h264parse/gsth264parse.c 2011-11-30 12:04:48.163610030 +0530 +@@ -38,19 +38,21 @@ + static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, +- GST_STATIC_CAPS ("video/x-h264")); ++ GST_STATIC_CAPS ("video/x-h264," ++ "framed = (boolean)false")); + + static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, +- GST_STATIC_CAPS ("video/x-h264")); ++ GST_STATIC_CAPS ("video/x-h264," ++ "framed = (boolean)true")); + + GST_DEBUG_CATEGORY_STATIC (h264_parse_debug); + #define GST_CAT_DEFAULT h264_parse_debug + +-#define DEFAULT_SPLIT_PACKETIZED FALSE +-#define DEFAULT_ACCESS_UNIT FALSE +-#define DEFAULT_OUTPUT_FORMAT GST_H264_PARSE_FORMAT_INPUT ++#define DEFAULT_SPLIT_PACKETIZED TRUE ++#define DEFAULT_ACCESS_UNIT TRUE ++#define DEFAULT_OUTPUT_FORMAT GST_H264_PARSE_FORMAT_BYTE + #define DEFAULT_CONFIG_INTERVAL (0) + + enum +@@ -964,7 +966,7 @@ gst_h264_parse_init (GstH264Parse * h264 + h264parse->interval = DEFAULT_CONFIG_INTERVAL; + h264parse->last_report = GST_CLOCK_TIME_NONE; + +- h264parse->format = GST_H264_PARSE_FORMAT_INPUT; ++ h264parse->format = DEFAULT_OUTPUT_FORMAT; + + gst_h264_parse_reset (h264parse); + } +@@ -1128,11 +1130,11 @@ gst_h264_parse_make_codec_data (GstH264P + num_sps++; + /* size bytes also count */ + sps_size += GST_BUFFER_SIZE (nal) - 4 + 2; +- if (GST_BUFFER_SIZE (nal) >= 7) { ++ if (GST_BUFFER_SIZE (nal) >= 8) { + found = TRUE; +- profile_idc = (GST_BUFFER_DATA (nal))[4]; +- profile_comp = (GST_BUFFER_DATA (nal))[5]; +- level_idc = (GST_BUFFER_DATA (nal))[6]; ++ profile_idc = (GST_BUFFER_DATA (nal))[5]; ++ profile_comp = (GST_BUFFER_DATA (nal))[6]; ++ level_idc = (GST_BUFFER_DATA (nal))[7]; + } + } + } +@@ -1307,16 +1309,18 @@ gst_h264_parse_update_src_caps (GstH264P + alignment = "au"; + } else { + if (h264parse->packetized) { +- /* if packetized input, take upstream alignment if validly provided, +- * otherwise assume au aligned ... */ +- alignment = gst_structure_get_string (structure, "alignment"); +- if (!alignment || (alignment && +- strcmp (alignment, "au") != 0 && +- strcmp (alignment, "nal") != 0)) { +- if (h264parse->split_packetized) +- alignment = "nal"; +- else ++ if (h264parse->split_packetized) ++ alignment = "nal"; ++ else { ++ /* if packetized input is not split, ++ * take upstream alignment if validly provided, ++ * otherwise assume au aligned ... */ ++ alignment = gst_structure_get_string (structure, "alignment"); ++ if (!alignment || (alignment && ++ strcmp (alignment, "au") != 0 && ++ strcmp (alignment, "nal") != 0)) { + alignment = "au"; ++ } + } + } else { + alignment = "nal"; +@@ -1596,7 +1600,7 @@ gst_h264_parse_push_codec_buffer (GstH26 + static GstFlowReturn + gst_h264_parse_push_buffer (GstH264Parse * h264parse, GstBuffer * buf) + { +- GstFlowReturn ret = GST_FLOW_OK; ++ GstFlowReturn res = GST_FLOW_OK; + + /* We can send pending events if this is the first call, since we now have + * caps for the srcpad */ +@@ -1615,6 +1619,33 @@ gst_h264_parse_push_buffer (GstH264Parse + } + } + ++ if (G_UNLIKELY (h264parse->width == 0 || h264parse->height == 0)) { ++ GST_DEBUG ("Delaying actual push until we are configured"); ++ h264parse->gather = g_list_append (h264parse->gather, buf); ++ goto beach; ++ } ++ ++ if (G_UNLIKELY (h264parse->gather)) { ++ GList *pendingbuffers = h264parse->gather; ++ GList *tmp; ++ ++ GST_DEBUG ("Pushing out pending buffers"); ++ ++ /* Yes, we're recursively calling in... */ ++ h264parse->gather = NULL; ++ for (tmp = pendingbuffers; tmp; tmp = tmp->next) { ++ res = gst_h264_parse_push_buffer (h264parse, (GstBuffer *) tmp->data); ++ if (res != GST_FLOW_OK && res != GST_FLOW_NOT_LINKED) ++ break; ++ } ++ g_list_free (pendingbuffers); ++ ++ if (res != GST_FLOW_OK && res != GST_FLOW_NOT_LINKED) { ++ gst_buffer_unref (buf); ++ goto beach; ++ } ++ } ++ + /* start of picture is good time to slip in codec_data NALUs + * (when outputting NALS and transforming to bytestream) */ + if (G_UNLIKELY (h264parse->codec_nals && h264parse->picture_start)) { +@@ -1626,7 +1657,7 @@ gst_h264_parse_push_buffer (GstH264Parse + GST_BUFFER_DURATION (nals->data) = 0; + + gst_buffer_set_caps (nals->data, h264parse->src_caps); +- ret = gst_pad_push (h264parse->srcpad, nals->data); ++ (void) gst_pad_push (h264parse->srcpad, nals->data); + nals = g_slist_delete_link (nals, nals); + } + h264parse->codec_nals = NULL; +@@ -1736,7 +1767,10 @@ gst_h264_parse_push_buffer (GstH264Parse + } + + gst_buffer_set_caps (buf, h264parse->src_caps); +- return gst_pad_push (h264parse->srcpad, buf); ++ res = gst_pad_push (h264parse->srcpad, buf); ++ ++beach: ++ return res; + } + + /* takes over ownership of nal and returns fresh buffer */ +@@ -1782,7 +1816,6 @@ gst_h264_parse_push_nal (GstH264Parse * + /* first_mb_in_slice == 0 considered start of frame */ + start = h264parse->picture_start && (data[nal_length + 1] & 0x80); + if (G_UNLIKELY (!next_nal)) { +- printf("Frame complete!!\n"); + complete = TRUE; + } else { + /* consider a coded slices (IDR or not) to start a picture, +@@ -2098,9 +2131,6 @@ gst_h264_parse_chain_forward (GstH264Par + + /* packetized will have no next data, which serves fine here */ + next_data = (guint8 *) gst_adapter_peek (h264parse->adapter, 6); +- GST_DEBUG("next_data:%p",next_data); +- if(next_data == NULL) +- return GST_FLOW_OK; + outbuf = gst_h264_parse_push_nal (h264parse, outbuf, next_data, &start); + if (!outbuf) { + /* no complete unit yet, go for next round */ +@@ -2110,10 +2140,10 @@ gst_h264_parse_chain_forward (GstH264Par + /* Ignore upstream dts that stalls or goes backward. Upstream elements + * like filesrc would keep on writing timestamp=0. XXX: is this correct? + * TODO: better way to detect whether upstream timstamps are useful */ +- if (h264parse->last_outbuf_dts != GST_CLOCK_TIME_NONE ++ /* if (h264parse->last_outbuf_dts != GST_CLOCK_TIME_NONE + && outbuf_dts != GST_CLOCK_TIME_NONE + && outbuf_dts <= h264parse->last_outbuf_dts) +- outbuf_dts = GST_CLOCK_TIME_NONE; ++ outbuf_dts = GST_CLOCK_TIME_NONE;*/ + + if ((got_frame || delta_unit) && start) { + GstH264Sps *sps = h264parse->sps; +@@ -2445,7 +2475,7 @@ gst_h264_parse_chain_reverse (GstH264Par + + /* if we have a discont, move buffers to the decode list */ + if (G_UNLIKELY (discont)) { +- guint start, stop, last; ++ guint start, last; + guint32 code; + GstBuffer *prev; + GstClockTime timestamp; +@@ -2454,7 +2484,6 @@ gst_h264_parse_chain_reverse (GstH264Par + "received discont, copy gathered buffers for decoding"); + + /* init start code accumulator */ +- stop = -1; + prev = h264parse->prev; + h264parse->prev = NULL; + +@@ -2700,7 +2729,7 @@ static gboolean + plugin_init (GstPlugin * plugin) + { + return gst_element_register (plugin, "h264parse", +- GST_RANK_NONE, GST_TYPE_H264PARSE); ++ (GST_RANK_PRIMARY + 1), GST_TYPE_H264PARSE); + } + + GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-bad-0.10.21/0009-mpeg4videoparse-push-flush-stop-and-new-segment b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-bad-0.10.21/0009-mpeg4videoparse-push-flush-stop-and-new-segment new file mode 100644 index 0000000..3672c07 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-bad-0.10.21/0009-mpeg4videoparse-push-flush-stop-and-new-segment @@ -0,0 +1,24 @@ +--- gst-plugins-bad-0.10.21.orig/gst/mpeg4videoparse/mpeg4videoparse.c 2010-12-24 17:29:38.000000000 +0530 ++++ gst-plugins-bad-0.10.21/gst/mpeg4videoparse/mpeg4videoparse.c 2012-01-15 17:06:11.053523827 +0530 +@@ -550,7 +550,12 @@ gst_mpeg4vparse_push (GstMpeg4VParse * p + parse->last_report = timestamp; + } + } +- } ++ } ++ if (parse->pending_segment != NULL) { ++ /* Send new segment event received after flush/seek etc.*/ ++ gst_pad_push_event (parse->srcpad, parse->pending_segment); ++ parse->pending_segment = NULL; ++ } + gst_buffer_set_caps (out_buf, GST_PAD_CAPS (parse->srcpad)); + gst_pad_push (parse->srcpad, out_buf); + } +@@ -806,6 +811,7 @@ gst_mpeg4vparse_sink_event (GstPad * pad + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: ++ res = gst_pad_event_default (pad, event); + parse->last_report = GST_CLOCK_TIME_NONE; + gst_adapter_clear (parse->adapter); + parse->state = PARSE_NEED_START; diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-base-0.10.32/0026-playbin-link-omx_scaler-to-do-HW-accel-scale-remove-identity.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-base-0.10.32/0026-playbin-link-omx_scaler-to-do-HW-accel-scale-remove-identity.patch new file mode 100644 index 0000000..d1abf80 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-base-0.10.32/0026-playbin-link-omx_scaler-to-do-HW-accel-scale-remove-identity.patch @@ -0,0 +1,50 @@ +--- gst-plugins-base-0.10.32.orig/gst/playback/gstplaybin.c 2010-10-13 17:24:05.000000000 +0530 ++++ gst-plugins-base-0.10.32/gst/playback/gstplaybin.c 2011-11-24 16:40:02.843360968 +0530 +@@ -830,7 +830,7 @@ gen_video_element (GstPlayBin * play_bin + GstElement *element; + GstElement *conv; + +- GstElement *scale; ++ //GstElement *scale; + GstElement *sink; + GstElement *identity; + GstPad *pad; +@@ -859,29 +859,29 @@ gen_video_element (GstPlayBin * play_bin + element = gst_bin_new ("vbin"); + gst_bin_add (GST_BIN_CAST (element), sink); + +- conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); ++ conv = gst_element_factory_make ("omx_scaler", "vconv"); + if (conv == NULL) + goto no_colorspace; + gst_bin_add (GST_BIN_CAST (element), conv); + +- scale = gst_element_factory_make ("videoscale", "vscale"); ++/* scale = gst_element_factory_make ("identity", "vscale"); + if (scale == NULL) + goto no_videoscale; +- gst_bin_add (GST_BIN_CAST (element), scale); ++ gst_bin_add (GST_BIN_CAST (element), scale);*/ + +- identity = gst_element_factory_make ("identity", "id"); ++ /* identity = gst_element_factory_make ("identity", "id"); + g_object_set (identity, "silent", TRUE, NULL); + g_signal_connect (identity, "handoff", G_CALLBACK (handoff), play_bin); +- gst_bin_add (GST_BIN_CAST (element), identity); ++ gst_bin_add (GST_BIN_CAST (element), identity);*/ + +- gst_element_link_pads (identity, "src", conv, "sink"); +- gst_element_link_pads (conv, "src", scale, "sink"); ++// gst_element_link_pads (identity, "src", conv, "sink"); ++ // gst_element_link_pads (conv, "src", scale, "sink"); + /* be more careful with the pad from the custom sink element, it might not + * be named 'sink' */ +- if (!gst_element_link_pads (scale, "src", sink, NULL)) ++ if (!gst_element_link_pads (conv, "src", sink, NULL)) + goto link_failed; + +- pad = gst_element_get_static_pad (identity, "sink"); ++ pad = gst_element_get_static_pad (conv, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-base-0.10.32/0026-playbin-link-omx_scaler-to-do-HW-accel-scale.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-base-0.10.32/0026-playbin-link-omx_scaler-to-do-HW-accel-scale.patch new file mode 100644 index 0000000..59c47f5 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-base-0.10.32/0026-playbin-link-omx_scaler-to-do-HW-accel-scale.patch @@ -0,0 +1,43 @@ +--- gst-plugins-base-0.10.32.orig/gst/playback/gstplaybin.c 2010-10-13 17:24:05.000000000 +0530 ++++ gst-plugins-base-0.10.32/gst/playback/gstplaybin.c 2011-11-18 17:38:05.287360205 +0530 +@@ -830,7 +830,7 @@ gen_video_element (GstPlayBin * play_bin + GstElement *element; + GstElement *conv; + +- GstElement *scale; ++ //GstElement *scale; + GstElement *sink; + GstElement *identity; + GstPad *pad; +@@ -859,15 +859,15 @@ gen_video_element (GstPlayBin * play_bin + element = gst_bin_new ("vbin"); + gst_bin_add (GST_BIN_CAST (element), sink); + +- conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); ++ conv = gst_element_factory_make ("omx_scaler", "vconv"); + if (conv == NULL) + goto no_colorspace; + gst_bin_add (GST_BIN_CAST (element), conv); + +- scale = gst_element_factory_make ("videoscale", "vscale"); ++/* scale = gst_element_factory_make ("identity", "vscale"); + if (scale == NULL) + goto no_videoscale; +- gst_bin_add (GST_BIN_CAST (element), scale); ++ gst_bin_add (GST_BIN_CAST (element), scale);*/ + + identity = gst_element_factory_make ("identity", "id"); + g_object_set (identity, "silent", TRUE, NULL); +@@ -875,10 +875,10 @@ gen_video_element (GstPlayBin * play_bin + gst_bin_add (GST_BIN_CAST (element), identity); + + gst_element_link_pads (identity, "src", conv, "sink"); +- gst_element_link_pads (conv, "src", scale, "sink"); ++ // gst_element_link_pads (conv, "src", scale, "sink"); + /* be more careful with the pad from the custom sink element, it might not + * be named 'sink' */ +- if (!gst_element_link_pads (scale, "src", sink, NULL)) ++ if (!gst_element_link_pads (conv, "src", sink, NULL)) + goto link_failed; + + pad = gst_element_get_static_pad (identity, "sink"); diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0001-v4l2-fix-handling-of-RGB32-BGR32-formats.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0001-v4l2-fix-handling-of-RGB32-BGR32-formats.patch new file mode 100644 index 0000000..623567d --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0001-v4l2-fix-handling-of-RGB32-BGR32-formats.patch @@ -0,0 +1,53 @@ +From 194aa8513c02fbfcabf04b45ff4c81bf8a94527f Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Tue, 14 Sep 2010 07:42:50 -0500 +Subject: [PATCH 01/11] v4l2: fix handling of RGB32/BGR32 formats + +bpp is 32, but depth is only 24.. +--- + sys/v4l2/gstv4l2object.c | 12 +++++++----- + 1 files changed, 7 insertions(+), 5 deletions(-) + +diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c +index 7e15489..f5672b5 100644 +--- a/sys/v4l2/gstv4l2object.c ++++ b/sys/v4l2/gstv4l2object.c +@@ -1132,14 +1132,16 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + b_mask = 0xff0000; + break; + case V4L2_PIX_FMT_RGB32: +- bpp = depth = 32; ++ depth = 24; ++ bpp = 32; + endianness = G_BIG_ENDIAN; + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; + break; + case V4L2_PIX_FMT_BGR32: +- bpp = depth = 32; ++ depth = 24; ++ bpp = 32; + endianness = G_BIG_ENDIAN; + r_mask = 0x000000ff; + g_mask = 0x0000ff00; +@@ -1404,13 +1406,13 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + #endif + } + } else if (!strcmp (mimetype, "video/x-raw-rgb")) { +- gint depth, endianness, r_mask; ++ gint bpp, endianness, r_mask; + +- gst_structure_get_int (structure, "depth", &depth); ++ gst_structure_get_int (structure, "bpp", &bpp); + gst_structure_get_int (structure, "endianness", &endianness); + gst_structure_get_int (structure, "red_mask", &r_mask); + +- switch (depth) { ++ switch (bpp) { + case 8: + fourcc = V4L2_PIX_FMT_RGB332; + break; +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0002-v4l2sink-Add-rotation-support.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0002-v4l2sink-Add-rotation-support.patch new file mode 100644 index 0000000..b405ea0 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0002-v4l2sink-Add-rotation-support.patch @@ -0,0 +1,128 @@ +From d43a9444fc5f7655a8acd2978039667a04222ba0 Mon Sep 17 00:00:00 2001 +From: Kiran Nataraju <knataraju@ti.com> +Date: Fri, 27 Aug 2010 09:00:57 +0200 +Subject: [PATCH 02/11] v4l2sink: Add rotation support. + +Signed-off-by: Kiran Nataraju <knataraju@ti.com> +Signed-off-by: Daniel Diaz <ddiaz@ti.com> +--- + sys/v4l2/gstv4l2sink.c | 34 ++++++++++++++++++++++++++++++++++ + sys/v4l2/gstv4l2sink.h | 1 + + 2 files changed, 35 insertions(+), 0 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index aa6785c..5abf915 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -72,6 +72,10 @@ GST_DEBUG_CATEGORY (v4l2sink_debug); + #define PROP_DEF_MIN_QUEUED_BUFS 1 + #define DEFAULT_PROP_DEVICE "/dev/video1" + ++#define MIN_ROTATION_ANGLE 0 ++#define MAX_ROTATION_ANGLE 360 ++#define DEFAULT_ROTATION_ANGLE 0 ++ + enum + { + PROP_0, +@@ -86,6 +90,7 @@ enum + PROP_CROP_LEFT, + PROP_CROP_WIDTH, + PROP_CROP_HEIGHT, ++ PROP_ROTATION, + }; + + +@@ -220,6 +225,7 @@ static GstFlowReturn gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); + static GstFlowReturn gst_v4l2sink_show_frame (GstBaseSink * bsink, + GstBuffer * buf); ++static void gst_v4l2sink_set_rotation (GstV4l2Sink * v4l2sink); + + static void + gst_v4l2sink_base_init (gpointer g_class) +@@ -306,6 +312,11 @@ gst_v4l2sink_class_init (GstV4l2SinkClass * klass) + "The height of the video crop; default is equal to negotiated image height", + 0, 0xffffffff, 0, G_PARAM_READWRITE)); + ++ g_object_class_install_property (gobject_class, PROP_ROTATION, ++ g_param_spec_int ("rotation", "Rotation angle", ++ "Rotation angle for the image", MIN_ROTATION_ANGLE, ++ MAX_ROTATION_ANGLE, DEFAULT_ROTATION_ANGLE, G_PARAM_READWRITE)); ++ + basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_get_caps); + basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_set_caps); + basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_v4l2sink_buffer_alloc); +@@ -336,6 +347,7 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink, GstV4l2SinkClass * klass) + v4l2sink->overlay_fields_set = 0; + v4l2sink->crop_fields_set = 0; + v4l2sink->state = 0; ++ v4l2sink->rotation = 0; + } + + +@@ -475,6 +487,20 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) + } + } + ++static void ++gst_v4l2sink_set_rotation (GstV4l2Sink * v4l2sink) ++{ ++ if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { ++ struct v4l2_control control; ++ gint fd = v4l2sink->v4l2object->video_fd; ++ ++ memset (&control, 0x00, sizeof (struct v4l2_control)); ++ control.id = V4L2_CID_ROTATE; ++ control.value = v4l2sink->rotation; ++ g_return_if_fail (v4l2_ioctl (fd, VIDIOC_S_CTRL, &control) >= 0); ++ } ++} ++ + + static void + gst_v4l2sink_set_property (GObject * object, +@@ -531,6 +557,10 @@ gst_v4l2sink_set_property (GObject * object, + v4l2sink->crop_fields_set |= RECT_HEIGHT_SET; + gst_v4l2sink_sync_crop_fields (v4l2sink); + break; ++ case PROP_ROTATION: ++ v4l2sink->rotation = g_value_get_int (value); ++ gst_v4l2sink_set_rotation (v4l2sink); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -578,6 +608,9 @@ gst_v4l2sink_get_property (GObject * object, + case PROP_CROP_HEIGHT: + g_value_set_uint (value, v4l2sink->crop.height); + break; ++ case PROP_ROTATION: ++ g_value_set_int (value, v4l2sink->rotation); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -600,6 +633,7 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition) + /* open the device */ + if (!gst_v4l2_object_start (v4l2sink->v4l2object)) + return GST_STATE_CHANGE_FAILURE; ++ gst_v4l2sink_set_rotation (v4l2sink); + break; + default: + break; +diff --git a/sys/v4l2/gstv4l2sink.h b/sys/v4l2/gstv4l2sink.h +index 8fe8222..1239621 100644 +--- a/sys/v4l2/gstv4l2sink.h ++++ b/sys/v4l2/gstv4l2sink.h +@@ -75,6 +75,7 @@ struct _GstV4l2Sink { + guint8 overlay_fields_set, crop_fields_set; + + guint8 state; ++ gint rotation; + }; + + struct _GstV4l2SinkClass { +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0003-v4l2sink-Add-flip-property.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0003-v4l2sink-Add-flip-property.patch new file mode 100644 index 0000000..09839ad --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0003-v4l2sink-Add-flip-property.patch @@ -0,0 +1,187 @@ +From 1381c64fd606d8ab7169eef52386139a4848c439 Mon Sep 17 00:00:00 2001 +From: Kiran Nataraju <knataraju@ti.com> +Date: Tue, 21 Sep 2010 06:21:23 +0200 +Subject: [PATCH 03/11] v4l2sink: Add flip property. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Kiran Nataraju <knataraju@ti.com> +Signed-off-by: Daniel DÃaz <yosoy@danieldiaz.org> +--- + sys/v4l2/gstv4l2sink.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-- + sys/v4l2/gstv4l2sink.h | 1 + + 2 files changed, 85 insertions(+), 4 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index 5abf915..6163747 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -91,6 +91,7 @@ enum + PROP_CROP_WIDTH, + PROP_CROP_HEIGHT, + PROP_ROTATION, ++ PROP_FLIP, + }; + + +@@ -129,6 +130,34 @@ gst_v4l2sink_iface_supported (GstImplementsInterface * iface, GType iface_type) + return TRUE; + } + ++/* ++ * Flip state ++ */ ++enum ++{ ++ FLIP_NONE = 0, ++ FLIP_HORIZONTAL = 1, ++ FLIP_VERTICAL = 2, ++}; ++ ++#define GST_TYPE_V4L2_FLIP (gst_v4l2_flip_get_type ()) ++static GType ++gst_v4l2_flip_get_type (void) ++{ ++ static GType type = 0; ++ ++ if (!type) { ++ static GEnumValue vals[] = { ++ {FLIP_NONE, "No Flip", "none"}, ++ {FLIP_HORIZONTAL, "Horizontal Flip", "horiz"}, ++ {FLIP_VERTICAL, "Vertical Flip", "vert"}, ++ {0, NULL, NULL}, ++ }; ++ type = g_enum_register_static ("GstV4l2SinkFlip", vals); ++ } ++ return type; ++} ++ + static void + gst_v4l2sink_interface_init (GstImplementsInterfaceClass * klass) + { +@@ -225,7 +254,7 @@ static GstFlowReturn gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); + static GstFlowReturn gst_v4l2sink_show_frame (GstBaseSink * bsink, + GstBuffer * buf); +-static void gst_v4l2sink_set_rotation (GstV4l2Sink * v4l2sink); ++static void gst_v4l2sink_sync_rotation (GstV4l2Sink * v4l2sink); + + static void + gst_v4l2sink_base_init (gpointer g_class) +@@ -317,6 +346,11 @@ gst_v4l2sink_class_init (GstV4l2SinkClass * klass) + "Rotation angle for the image", MIN_ROTATION_ANGLE, + MAX_ROTATION_ANGLE, DEFAULT_ROTATION_ANGLE, G_PARAM_READWRITE)); + ++ g_object_class_install_property (gobject_class, PROP_FLIP, ++ g_param_spec_enum ("flip", "Flip State", ++ "Flip horizontal/vertical", ++ GST_TYPE_V4L2_FLIP, FLIP_NONE, G_PARAM_READWRITE)); ++ + basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_get_caps); + basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_set_caps); + basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_v4l2sink_buffer_alloc); +@@ -348,8 +382,46 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink, GstV4l2SinkClass * klass) + v4l2sink->crop_fields_set = 0; + v4l2sink->state = 0; + v4l2sink->rotation = 0; ++ v4l2sink->flip = FLIP_NONE; + } + ++static void ++gst_v4l2sink_sync_flip (GstV4l2Sink * v4l2sink) ++{ ++ if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { ++ struct v4l2_control control; ++ gint fd = v4l2sink->v4l2object->video_fd; ++ ++ memset (&control, 0x00, sizeof (struct v4l2_control)); ++ ++ switch (v4l2sink->flip) { ++ case FLIP_VERTICAL: ++ v4l2sink->rotation = 0; ++ control.value = 1; ++ break; ++ case FLIP_HORIZONTAL: ++ /* Horizontal Flip = Vertical Flip + 180 rotation */ ++ v4l2sink->rotation = 180; ++ control.value = 1; ++ break; ++ case FLIP_NONE: ++ /* In the below switch case logic we need to handle FLIP_NONE ++ * case since the v4l2 driver holds on to the last configured ++ * flip value even after the device file is closed. ++ */ ++ control.value = 0; ++ break; ++ default: ++ GST_WARNING_OBJECT (v4l2sink, "Invalid flip property"); ++ control.value = 0; ++ break; ++ } ++ ++ gst_v4l2sink_sync_rotation (v4l2sink); ++ control.id = V4L2_CID_VFLIP; ++ g_return_if_fail (v4l2_ioctl (fd, VIDIOC_S_CTRL, &control) >= 0); ++ } ++} + + static void + gst_v4l2sink_dispose (GObject * object) +@@ -488,7 +560,7 @@ gst_v4l2sink_sync_crop_fields (GstV4l2Sink * v4l2sink) + } + + static void +-gst_v4l2sink_set_rotation (GstV4l2Sink * v4l2sink) ++gst_v4l2sink_sync_rotation (GstV4l2Sink * v4l2sink) + { + if (GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { + struct v4l2_control control; +@@ -559,7 +631,11 @@ gst_v4l2sink_set_property (GObject * object, + break; + case PROP_ROTATION: + v4l2sink->rotation = g_value_get_int (value); +- gst_v4l2sink_set_rotation (v4l2sink); ++ gst_v4l2sink_sync_rotation (v4l2sink); ++ break; ++ case PROP_FLIP: ++ v4l2sink->flip = g_value_get_enum (value); ++ gst_v4l2sink_sync_flip (v4l2sink); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +@@ -611,6 +687,9 @@ gst_v4l2sink_get_property (GObject * object, + case PROP_ROTATION: + g_value_set_int (value, v4l2sink->rotation); + break; ++ case PROP_FLIP: ++ g_value_set_enum (value, v4l2sink->flip); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -633,7 +712,8 @@ gst_v4l2sink_change_state (GstElement * element, GstStateChange transition) + /* open the device */ + if (!gst_v4l2_object_start (v4l2sink->v4l2object)) + return GST_STATE_CHANGE_FAILURE; +- gst_v4l2sink_set_rotation (v4l2sink); ++ gst_v4l2sink_sync_rotation (v4l2sink); ++ gst_v4l2sink_sync_flip (v4l2sink); + break; + default: + break; +diff --git a/sys/v4l2/gstv4l2sink.h b/sys/v4l2/gstv4l2sink.h +index 1239621..907973a 100644 +--- a/sys/v4l2/gstv4l2sink.h ++++ b/sys/v4l2/gstv4l2sink.h +@@ -76,6 +76,7 @@ struct _GstV4l2Sink { + + guint8 state; + gint rotation; ++ gint flip; + }; + + struct _GstV4l2SinkClass { +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0004-v4l2sink-Add-support-for-omap24xxvout-driver.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0004-v4l2sink-Add-support-for-omap24xxvout-driver.patch new file mode 100644 index 0000000..528e9a6 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0004-v4l2sink-Add-support-for-omap24xxvout-driver.patch @@ -0,0 +1,59 @@ +From 39de525898eea073c1f2486b99b56ef25b6df289 Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Sun, 4 Apr 2010 06:46:21 -0500 +Subject: [PATCH 04/11] v4l2sink: Add support for omap24xxvout driver + +--- + sys/v4l2/gstv4l2sink.c | 22 +++++++++++++++++++++- + 1 files changed, 21 insertions(+), 1 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index 6163747..4408428 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -888,6 +888,18 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + /* initialize the buffer pool if not initialized yet (first buffer): */ + if (G_UNLIKELY (!v4l2sink->pool)) { + ++ gboolean no_pending_streamon = FALSE; ++ char *driver = (char *) v4l2sink->v4l2object->vcap.driver; ++ ++ /* the omap24xxvout driver wants us to start streaming before we ++ * queue the first buffer: ++ */ ++ if (!strcmp ("omap24xxvout", driver)) { ++ GST_DEBUG_OBJECT (v4l2sink, ++ "enabling no_pending_streamon hack for omap24xxvout driver"); ++ no_pending_streamon = TRUE; ++ } ++ + /* set_caps() might not be called yet.. so just to make sure: */ + if (!gst_v4l2sink_set_caps (bsink, caps)) { + return GST_FLOW_ERROR; +@@ -909,7 +921,14 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + gst_v4l2_xoverlay_prepare_xwindow_id (v4l2sink->v4l2object, TRUE); + #endif + +- v4l2sink->state = STATE_PENDING_STREAMON; ++ if (no_pending_streamon) { ++ if (!gst_v4l2_object_start_streaming (v4l2sink->v4l2object)) { ++ return GST_FLOW_ERROR; ++ } ++ v4l2sink->state = STATE_STREAMING; ++ } else { ++ v4l2sink->state = STATE_PENDING_STREAMON; ++ } + + GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()"); + +@@ -996,6 +1015,7 @@ gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) + if (!gst_v4l2_buffer_pool_qbuf (v4l2sink->pool, GST_V4L2_BUFFER (buf))) { + return GST_FLOW_ERROR; + } ++ + if (v4l2sink->state == STATE_PENDING_STREAMON) { + if (!gst_v4l2_object_start_streaming (v4l2sink->v4l2object)) { + return GST_FLOW_ERROR; +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0005-v4l2sink-Add-support-for-omap_vout-driver.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0005-v4l2sink-Add-support-for-omap_vout-driver.patch new file mode 100644 index 0000000..7ec58cd --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0005-v4l2sink-Add-support-for-omap_vout-driver.patch @@ -0,0 +1,34 @@ +From 1fabe36f40e872942c80041225bdbf41db561bea Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Sun, 4 Apr 2010 06:47:55 -0500 +Subject: [PATCH 05/11] v4l2sink: Add support for omap_vout driver + +--- + sys/v4l2/gstv4l2sink.c | 11 +++++++++++ + 1 files changed, 11 insertions(+), 0 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index 4408428..66dda8e 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -900,6 +900,17 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + no_pending_streamon = TRUE; + } + ++ /* workaround for bug in omap_vout driver, when we ask for more ++ * than four buffers: ++ */ ++ if (!strcmp ("omap_vout", driver)) { ++ if (v4l2sink->num_buffers > 4) { ++ v4l2sink->num_buffers = 4; ++ GST_DEBUG_OBJECT (v4l2sink, ++ "limiting to 4 buffers to work-around omap_vout driver bug"); ++ } ++ } ++ + /* set_caps() might not be called yet.. so just to make sure: */ + if (!gst_v4l2sink_set_caps (bsink, caps)) { + return GST_FLOW_ERROR; +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0006-v4l2-increase-v4l2sink-element-rank.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0006-v4l2-increase-v4l2sink-element-rank.patch new file mode 100644 index 0000000..cd417e3 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0006-v4l2-increase-v4l2sink-element-rank.patch @@ -0,0 +1,26 @@ +From 14d6f0fac0875981c418ac6577d23eafb5ff3f01 Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Wed, 14 Apr 2010 03:29:20 -0500 +Subject: [PATCH 06/11] v4l2: increase v4l2sink element rank + +Increase rank so that it is autoplugged. +--- + sys/v4l2/gstv4l2.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/sys/v4l2/gstv4l2.c b/sys/v4l2/gstv4l2.c +index 4a7056f..cba4157 100644 +--- a/sys/v4l2/gstv4l2.c ++++ b/sys/v4l2/gstv4l2.c +@@ -55,7 +55,7 @@ plugin_init (GstPlugin * plugin) + if (!gst_element_register (plugin, "v4l2src", GST_RANK_PRIMARY, + GST_TYPE_V4L2SRC) || + #ifdef HAVE_EXPERIMENTAL +- !gst_element_register (plugin, "v4l2sink", GST_RANK_NONE, ++ !gst_element_register (plugin, "v4l2sink", GST_RANK_PRIMARY, + GST_TYPE_V4L2SINK) || + #endif + /* !gst_element_register (plugin, "v4l2jpegsrc", */ +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0007-use-GstQueryBuffers-to-get-buffer-requirements.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0007-use-GstQueryBuffers-to-get-buffer-requirements.patch new file mode 100644 index 0000000..70ceae5 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0007-use-GstQueryBuffers-to-get-buffer-requirements.patch @@ -0,0 +1,97 @@ +From 15c17ea368079fd5de19868af6d9ffad1cb09f3a Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Wed, 19 May 2010 17:33:46 -0500 +Subject: [PATCH 07/11] use GstQueryBuffers to get buffer requirements + +--- + sys/v4l2/gstv4l2sink.c | 40 ++++++++++++++++++++++++++++++++++++++++ + sys/v4l2/gstv4l2sink.h | 1 + + 2 files changed, 41 insertions(+), 0 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index 66dda8e..12323f7 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -373,6 +373,7 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sink, GstV4l2SinkClass * klass) + + /* number of buffers requested */ + v4l2sink->num_buffers = PROP_DEF_QUEUE_SIZE; ++ v4l2sink->num_buffers_can_change = TRUE; + v4l2sink->min_queued_bufs = PROP_DEF_MIN_QUEUED_BUFS; + + v4l2sink->probed_caps = NULL; +@@ -808,6 +809,7 @@ static gboolean + gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + { + GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); ++ GstQuery *query; + gint w = 0, h = 0; + gboolean interlaced; + struct v4l2_fmtdesc *format; +@@ -855,6 +857,39 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + return FALSE; + } + ++ /* query to find if anyone upstream using these buffers has any ++ * minimum requirements: ++ */ ++ query = gst_query_new_buffers (caps); ++ if (gst_element_query (GST_ELEMENT (v4l2sink), query)) { ++ gint min_buffers, min_width, min_height; ++ ++ gst_query_parse_buffers_count (query, &min_buffers); ++ ++ /* XXX need to account for some buffers used by queue, etc.. probably ++ * queue should handle query, pass on to sink pad, and then add some ++ * number of buffers to the min, so this value is dynamic depending ++ * on the pipeline? ++ */ ++ if (min_buffers != -1) { ++ min_buffers += 3 + v4l2sink->min_queued_bufs; ++ } ++ ++ if (min_buffers > v4l2sink->num_buffers) { ++ v4l2sink->num_buffers_can_change = FALSE; ++ v4l2sink->num_buffers = min_buffers; ++ } ++ ++ gst_query_parse_buffers_dimensions (query, &min_width, &min_height); ++ if (min_width > w) { ++ w = min_width; ++ } ++ if (min_height > h) { ++ h = min_height; ++ } ++ } ++ gst_query_unref (query); ++ + if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat, + w, h, interlaced)) { + /* error already posted */ +@@ -944,6 +979,11 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()"); + + if (v4l2sink->num_buffers != v4l2sink->pool->buffer_count) { ++ if (!v4l2sink->num_buffers_can_change) { ++ GST_WARNING_OBJECT (v4l2sink, ++ "I can't handle a differing number of buffers!!!!"); ++ return GST_FLOW_ERROR; ++ } + v4l2sink->num_buffers = v4l2sink->pool->buffer_count; + g_object_notify (G_OBJECT (v4l2sink), "queue-size"); + } +diff --git a/sys/v4l2/gstv4l2sink.h b/sys/v4l2/gstv4l2sink.h +index 907973a..7649fa1 100644 +--- a/sys/v4l2/gstv4l2sink.h ++++ b/sys/v4l2/gstv4l2sink.h +@@ -58,6 +58,7 @@ struct _GstV4l2Sink { + GstCaps *current_caps; /* the current negotiated caps */ + GstV4l2BufferPool *pool; + guint32 num_buffers; ++ gboolean num_buffers_can_change; + guint32 min_queued_bufs; + + gint video_width, video_height; /* original (unscaled) video w/h */ +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0008-add-rowstride-support.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0008-add-rowstride-support.patch new file mode 100644 index 0000000..1075a89 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0008-add-rowstride-support.patch @@ -0,0 +1,572 @@ +From a86d0326df31103c2ee38ee1e0c62802a758ef13 Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Fri, 21 May 2010 15:21:32 -0500 +Subject: [PATCH 08/11] add rowstride support + +--- + sys/v4l2/gstv4l2object.c | 141 +++++++++++++++++++++++++++++++++++++--------- + sys/v4l2/gstv4l2object.h | 6 +- + sys/v4l2/gstv4l2sink.c | 61 +++++++++++++------- + sys/v4l2/gstv4l2src.c | 28 +++++---- + 4 files changed, 174 insertions(+), 62 deletions(-) + +diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c +index f5672b5..5e34456 100644 +--- a/sys/v4l2/gstv4l2object.c ++++ b/sys/v4l2/gstv4l2object.c +@@ -1064,16 +1064,23 @@ gst_v4l2_object_get_format_list (GstV4l2Object * v4l2object) + return v4l2object->formats; + } + +- +-GstStructure * +-gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) ++/* ++ * gst_v4l2_object_v4l2fourcc_to_structures: ++ * @fourcc: requested format ++ * @structures: an array of at least MAX_STRUCTS_PER_FOURCC to return the ++ * results in ++ * ++ * Returns the number of structures returned via structures ++ */ ++gint ++gst_v4l2_object_v4l2fourcc_to_structures (guint32 fourcc, ++ GstStructure ** structures) + { +- GstStructure *structure = NULL; +- ++ gint count = 0; + switch (fourcc) { + case V4L2_PIX_FMT_MJPEG: /* Motion-JPEG */ + case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */ +- structure = gst_structure_new ("image/jpeg", NULL); ++ structures[count++] = gst_structure_new ("image/jpeg", NULL); + break; + case V4L2_PIX_FMT_RGB332: + case V4L2_PIX_FMT_RGB555: +@@ -1151,17 +1158,25 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + g_assert_not_reached (); + break; + } +- structure = gst_structure_new ("video/x-raw-rgb", ++ structures[count++] = gst_structure_new ("video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "red_mask", G_TYPE_INT, r_mask, + "green_mask", G_TYPE_INT, g_mask, + "blue_mask", G_TYPE_INT, b_mask, + "endianness", G_TYPE_INT, endianness, NULL); ++ structures[count++] = gst_structure_new ("video/x-raw-rgb-strided", ++ "bpp", G_TYPE_INT, bpp, ++ "depth", G_TYPE_INT, depth, ++ "red_mask", G_TYPE_INT, r_mask, ++ "green_mask", G_TYPE_INT, g_mask, ++ "blue_mask", G_TYPE_INT, b_mask, ++ "endianness", G_TYPE_INT, endianness, ++ "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + break; + } + case V4L2_PIX_FMT_GREY: /* 8 Greyscale */ +- structure = gst_structure_new ("video/x-raw-gray", ++ structures[count++] = gst_structure_new ("video/x-raw-gray", + "bpp", G_TYPE_INT, 8, NULL); + break; + case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */ +@@ -1227,38 +1242,41 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + g_assert_not_reached (); + break; + } +- structure = gst_structure_new ("video/x-raw-yuv", ++ structures[count++] = gst_structure_new ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, fcc, NULL); ++ structures[count++] = gst_structure_new ("video/x-raw-yuv-strided", ++ "format", GST_TYPE_FOURCC, fcc, ++ "rowstride", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + break; + } + case V4L2_PIX_FMT_DV: +- structure = ++ structures[count++] = + gst_structure_new ("video/x-dv", "systemstream", G_TYPE_BOOLEAN, TRUE, + NULL); + break; + case V4L2_PIX_FMT_MPEG: /* MPEG */ +- structure = gst_structure_new ("video/mpegts", NULL); ++ structures[count++] = gst_structure_new ("video/mpegts", NULL); + break; + case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */ + break; + #ifdef V4L2_PIX_FMT_SBGGR8 + case V4L2_PIX_FMT_SBGGR8: +- structure = gst_structure_new ("video/x-raw-bayer", NULL); ++ structures[count++] = gst_structure_new ("video/x-raw-bayer", NULL); + break; + #endif + #ifdef V4L2_PIX_FMT_SN9C10X + case V4L2_PIX_FMT_SN9C10X: +- structure = gst_structure_new ("video/x-sonix", NULL); ++ structures[count++] = gst_structure_new ("video/x-sonix", NULL); + break; + #endif + #ifdef V4L2_PIX_FMT_PWC1 + case V4L2_PIX_FMT_PWC1: +- structure = gst_structure_new ("video/x-pwc1", NULL); ++ structures[count++] = gst_structure_new ("video/x-pwc1", NULL); + break; + #endif + #ifdef V4L2_PIX_FMT_PWC2 + case V4L2_PIX_FMT_PWC2: +- structure = gst_structure_new ("video/x-pwc2", NULL); ++ structures[count++] = gst_structure_new ("video/x-pwc2", NULL); + break; + #endif + default: +@@ -1267,7 +1285,7 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc) + break; + } + +- return structure; ++ return count; + } + + +@@ -1278,22 +1296,23 @@ gst_v4l2_object_get_all_caps (void) + static GstCaps *caps = NULL; + + if (caps == NULL) { +- GstStructure *structure; +- + guint i; + + caps = gst_caps_new_empty (); + for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) { +- structure = +- gst_v4l2_object_v4l2fourcc_to_structure (gst_v4l2_formats[i].format); +- if (structure) { ++ GstStructure *structures[MAX_STRUCTS_PER_FOURCC]; ++ gint count, j; ++ count = ++ gst_v4l2_object_v4l2fourcc_to_structures (gst_v4l2_formats[i].format, ++ structures); ++ for (j = 0; j < count; j++) { + if (gst_v4l2_formats[i].dimensions) { +- gst_structure_set (structure, ++ gst_structure_set (structures[j], + "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE, + "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL); + } +- gst_caps_append_structure (caps, structure); ++ gst_caps_append_structure (caps, structures[j]); + } + } + } +@@ -1306,12 +1325,14 @@ gst_v4l2_object_get_all_caps (void) + * @caps: given input caps + * @format: location for the v4l format + * @w/@h: location for width and height ++ * @rs: required rowstride in bytes, or 0 if natural stride (based on format ++ * and width) or not-applicable + * @fps_n/@fps_d: location for framerate + * @size: location for expected size of the frame or 0 if unknown + */ + gboolean + gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, +- struct v4l2_fmtdesc ** format, gint * w, gint * h, ++ struct v4l2_fmtdesc ** format, gint * w, gint * h, gint * rs, + gboolean * interlaced, guint * fps_n, guint * fps_d, guint * size) + { + GstStructure *structure; +@@ -1319,10 +1340,12 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + guint32 fourcc; + const gchar *mimetype; + guint outsize; ++ struct v4l2_format fmt = { 0, }; + + /* default unknown values */ + fourcc = 0; + outsize = 0; ++ *rs = 0; + + structure = gst_caps_get_structure (caps, 0); + +@@ -1351,61 +1374,73 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + *fps_n = gst_value_get_fraction_numerator (framerate); + *fps_d = gst_value_get_fraction_denominator (framerate); + +- if (!strcmp (mimetype, "video/x-raw-yuv")) { ++ if (!strcmp (mimetype, "video/x-raw-yuv") || ++ !strcmp (mimetype, "video/x-raw-yuv-strided")) { + gst_structure_get_fourcc (structure, "format", &fourcc); + + switch (fourcc) { + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'): + fourcc = V4L2_PIX_FMT_YUV420; ++ *rs = GST_ROUND_UP_4 (*w); + outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h); + outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2)); + break; + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + fourcc = V4L2_PIX_FMT_YUYV; ++ *rs = GST_ROUND_UP_2 (*w) * 2; + outsize = (GST_ROUND_UP_2 (*w) * 2) * *h; + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'P'): + fourcc = V4L2_PIX_FMT_Y41P; ++ *rs = GST_ROUND_UP_2 (*w) * 2; + outsize = (GST_ROUND_UP_2 (*w) * 2) * *h; + break; + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + fourcc = V4L2_PIX_FMT_UYVY; ++ *rs = GST_ROUND_UP_2 (*w) * 2; + outsize = (GST_ROUND_UP_2 (*w) * 2) * *h; + break; + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + fourcc = V4L2_PIX_FMT_YVU420; ++ *rs = GST_ROUND_UP_4 (*w); + outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h); + outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2)); + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): + fourcc = V4L2_PIX_FMT_YUV411P; ++ *rs = GST_ROUND_UP_4 (*w); + outsize = GST_ROUND_UP_4 (*w) * *h; + outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h); + break; + case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): + fourcc = V4L2_PIX_FMT_YUV422P; ++ *rs = GST_ROUND_UP_4 (*w); + outsize = GST_ROUND_UP_4 (*w) * *h; + outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h); + break; + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + fourcc = V4L2_PIX_FMT_NV12; ++ *rs = GST_ROUND_UP_4 (*w); + outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h); + outsize += (GST_ROUND_UP_4 (*w) * *h) / 2; + break; + case GST_MAKE_FOURCC ('N', 'V', '2', '1'): + fourcc = V4L2_PIX_FMT_NV21; ++ *rs = GST_ROUND_UP_4 (*w); + outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h); + outsize += (GST_ROUND_UP_4 (*w) * *h) / 2; + break; + #ifdef V4L2_PIX_FMT_YVYU + case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): + fourcc = V4L2_PIX_FMT_YVYU; ++ *rs = GST_ROUND_UP_2 (*w) * 2; + outsize = (GST_ROUND_UP_2 (*w) * 2) * *h; + break; + #endif + } +- } else if (!strcmp (mimetype, "video/x-raw-rgb")) { ++ } else if (!strcmp (mimetype, "video/x-raw-rgb") || ++ !strcmp (mimetype, "video/x-raw-rgb-strided")) { + gint bpp, endianness, r_mask; + + gst_structure_get_int (structure, "bpp", &bpp); +@@ -1415,20 +1450,25 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + switch (bpp) { + case 8: + fourcc = V4L2_PIX_FMT_RGB332; ++ *rs = *w; + break; + case 15: + fourcc = (endianness == G_LITTLE_ENDIAN) ? + V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X; ++ *rs = 2 * *w; + break; + case 16: + fourcc = (endianness == G_LITTLE_ENDIAN) ? + V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X; ++ *rs = 2 * *w; + break; + case 24: + fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24; ++ *rs = 3 * *w; + break; + case 32: + fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32; ++ *rs = 4 * *w; + break; + } + } else if (strcmp (mimetype, "video/x-dv") == 0) { +@@ -1458,6 +1498,25 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps, + if (fourcc == 0) + return FALSE; + ++ /* check what stride the driver supports */ ++ fmt.type = v4l2object->type; ++ fmt.fmt.pix.width = *w; ++ fmt.fmt.pix.height = *h; ++ fmt.fmt.pix.pixelformat = fourcc; ++ fmt.fmt.pix.field = V4L2_FIELD_ANY; ++ fmt.fmt.pix.bytesperline = *rs; ++ if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_TRY_FMT, &fmt) >= 0) { ++ if (fmt.fmt.pix.bytesperline == *rs) { ++ *rs = 0; ++ } else { ++ *rs = fmt.fmt.pix.bytesperline; ++ } ++ GST_INFO_OBJECT (v4l2object->element, "rowstride: %d", *rs); ++ } else { ++ GST_WARNING_OBJECT (v4l2object->element, ++ "VIDIOC_TRY_FMT should not fail.. driver problem?"); ++ } ++ + done: + *format = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc); + *size = outsize; +@@ -1465,6 +1524,36 @@ done: + return TRUE; + } + ++/* Update caps to reflect rowstride that has been requested by the ++ * driver ++ */ ++GstCaps * ++gst_v4l2_object_update_rowstride (GstV4l2Object * v4l2object, ++ GstCaps * caps, gint rs) ++{ ++ GstStructure *structure; ++ const gchar *mimetype; ++ ++ caps = gst_caps_make_writable (caps); ++ ++ structure = gst_caps_get_structure (caps, 0); ++ mimetype = gst_structure_get_name (structure); ++ ++ if (!strcmp (mimetype, "video/x-raw-yuv")) { ++ mimetype = "video/x-raw-yuv-strided"; ++ gst_structure_set_name (structure, mimetype); ++ } else if (!strcmp (mimetype, "video/x-raw-rgb")) { ++ mimetype = "video/x-raw-rgb-strided"; ++ gst_structure_set_name (structure, mimetype); ++ } ++ ++ if (!strcmp (mimetype, "video/x-raw-yuv-strided") || ++ !strcmp (mimetype, "video/x-raw-rgb-strided")) { ++ gst_structure_set (structure, "rowstride", G_TYPE_INT, rs, NULL); ++ } ++ ++ return caps; ++} + + static gboolean + gst_v4l2_object_get_nearest_size (GstV4l2Object * v4l2object, +diff --git a/sys/v4l2/gstv4l2object.h b/sys/v4l2/gstv4l2object.h +index a0dd41c..228e7c7 100644 +--- a/sys/v4l2/gstv4l2object.h ++++ b/sys/v4l2/gstv4l2object.h +@@ -179,15 +179,17 @@ GstCaps* gst_v4l2_object_probe_caps_for_format (GstV4l2Object *v4l2object, + const GstStructure * template); + + gboolean gst_v4l2_object_get_caps_info (GstV4l2Object *v4l2object, GstCaps *caps, +- struct v4l2_fmtdesc **format, gint *w, gint *h, ++ struct v4l2_fmtdesc **format, gint *w, gint *h, gint *rs, + gboolean * interlaced, guint *fps_n, guint *fps_d, guint *size); + ++GstCaps * gst_v4l2_object_update_rowstride (GstV4l2Object * v4l2object, GstCaps * caps, gint rs); + + GSList* gst_v4l2_object_get_format_list (GstV4l2Object *v4l2object); + + GstCaps* gst_v4l2_object_get_all_caps (void); + +-GstStructure* gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc); ++#define MAX_STRUCTS_PER_FOURCC 2 ++gint gst_v4l2_object_v4l2fourcc_to_structures (guint32 fourcc, GstStructure ** structures); + + gboolean gst_v4l2_object_set_format (GstV4l2Object *v4l2object, guint32 pixelformat, guint32 width, guint32 height, gboolean interlaced); + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index 12323f7..a1f78cf 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -776,24 +776,23 @@ gst_v4l2sink_get_caps (GstBaseSink * bsink) + for (walk = v4l2sink->v4l2object->formats; walk; walk = walk->next) { + struct v4l2_fmtdesc *format; + +- GstStructure *template; ++ GstStructure *templates[MAX_STRUCTS_PER_FOURCC]; ++ gint count, i; + + format = (struct v4l2_fmtdesc *) walk->data; + +- template = gst_v4l2_object_v4l2fourcc_to_structure (format->pixelformat); ++ count = gst_v4l2_object_v4l2fourcc_to_structures (format->pixelformat, ++ templates); + +- if (template) { ++ for (i = 0; i < count; i++) { + GstCaps *tmp; + +- tmp = +- gst_v4l2_object_probe_caps_for_format (v4l2sink->v4l2object, +- format->pixelformat, template); ++ tmp = gst_v4l2_object_probe_caps_for_format (v4l2sink->v4l2object, ++ format->pixelformat, templates[i]); + if (tmp) + gst_caps_append (ret, tmp); + +- gst_structure_free (template); +- } else { +- GST_DEBUG_OBJECT (v4l2sink, "unknown format %u", format->pixelformat); ++ gst_structure_free (templates[i]); + } + } + +@@ -810,7 +809,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + { + GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); + GstQuery *query; +- gint w = 0, h = 0; ++ gint w = 0, h = 0, rs = 0; + gboolean interlaced; + struct v4l2_fmtdesc *format; + guint fps_n, fps_d; +@@ -823,11 +822,36 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + return FALSE; + } + ++ /* we want our own v4l2 type of fourcc codes */ ++ if (!gst_v4l2_object_get_caps_info (v4l2sink->v4l2object, caps, ++ &format, &w, &h, &rs, &interlaced, &fps_n, &fps_d, &size)) { ++ GST_DEBUG_OBJECT (v4l2sink, "can't get capture format from caps %p", caps); ++ return FALSE; ++ } ++ ++ if (!format) { ++ GST_DEBUG_OBJECT (v4l2sink, "unrecognized caps!!"); ++ return FALSE; ++ } ++ ++ /* we need to make our own ref before we potentially update the ++ * caps, to avoid that we release a ref that is not owned by us ++ * when we make the caps writable ++ */ ++ caps = gst_caps_ref (caps); ++ ++ /* if necessary, update caps for rowstride */ ++ if (rs) { ++ caps = gst_v4l2_object_update_rowstride (v4l2sink->v4l2object, caps, rs); ++ GST_DEBUG_OBJECT (v4l2sink, "updated caps: %" GST_PTR_FORMAT, caps); ++ } ++ + if (v4l2sink->current_caps) { + GST_DEBUG_OBJECT (v4l2sink, "already have caps set.. are they equal?"); + LOG_CAPS (v4l2sink, v4l2sink->current_caps); + if (gst_caps_is_equal (v4l2sink->current_caps, caps)) { + GST_DEBUG_OBJECT (v4l2sink, "yes they are!"); ++ gst_caps_unref (caps); + return TRUE; + } + GST_DEBUG_OBJECT (v4l2sink, "no they aren't!"); +@@ -842,18 +866,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + * + */ + GST_DEBUG_OBJECT (v4l2sink, "warning, changing caps not supported yet"); +- return FALSE; +- } +- +- /* we want our own v4l2 type of fourcc codes */ +- if (!gst_v4l2_object_get_caps_info (v4l2sink->v4l2object, caps, +- &format, &w, &h, &interlaced, &fps_n, &fps_d, &size)) { +- GST_DEBUG_OBJECT (v4l2sink, "can't get capture format from caps %p", caps); +- return FALSE; +- } +- +- if (!format) { +- GST_DEBUG_OBJECT (v4l2sink, "unrecognized caps!!"); ++ gst_caps_unref (caps); + return FALSE; + } + +@@ -893,6 +906,7 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, format->pixelformat, + w, h, interlaced)) { + /* error already posted */ ++ gst_caps_unref (caps); + return FALSE; + } + +@@ -951,6 +965,9 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + return GST_FLOW_ERROR; + } + ++ /* caps may have changed in _set_caps() if we need rowstride */ ++ caps = v4l2sink->current_caps; ++ + GST_V4L2_CHECK_OPEN (v4l2sink->v4l2object); + + if (!(v4l2sink->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2sink), +diff --git a/sys/v4l2/gstv4l2src.c b/sys/v4l2/gstv4l2src.c +index 4a37d35..a9a7787 100644 +--- a/sys/v4l2/gstv4l2src.c ++++ b/sys/v4l2/gstv4l2src.c +@@ -581,24 +581,23 @@ gst_v4l2src_get_caps (GstBaseSrc * src) + for (walk = v4l2src->v4l2object->formats; walk; walk = walk->next) { + struct v4l2_fmtdesc *format; + +- GstStructure *template; ++ GstStructure *templates[MAX_STRUCTS_PER_FOURCC]; ++ gint count, i; + + format = (struct v4l2_fmtdesc *) walk->data; + +- template = gst_v4l2_object_v4l2fourcc_to_structure (format->pixelformat); ++ count = gst_v4l2_object_v4l2fourcc_to_structures (format->pixelformat, ++ templates); + +- if (template) { ++ for (i = 0; i < count; i++) { + GstCaps *tmp; + +- tmp = +- gst_v4l2_object_probe_caps_for_format (v4l2src->v4l2object, +- format->pixelformat, template); ++ tmp = gst_v4l2_object_probe_caps_for_format (v4l2src->v4l2object, ++ format->pixelformat, templates[i]); + if (tmp) + gst_caps_append (ret, tmp); + +- gst_structure_free (template); +- } else { +- GST_DEBUG_OBJECT (v4l2src, "unknown format %u", format->pixelformat); ++ gst_structure_free (templates[i]); + } + } + +@@ -613,7 +612,7 @@ static gboolean + gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + { + GstV4l2Src *v4l2src; +- gint w = 0, h = 0; ++ gint w = 0, h = 0, rs = 0; + gboolean interlaced; + struct v4l2_fmtdesc *format; + guint fps_n, fps_d; +@@ -635,13 +634,18 @@ gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + } + + /* we want our own v4l2 type of fourcc codes */ +- if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, &w, +- &h, &interlaced, &fps_n, &fps_d, &size)) { ++ if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, ++ &w, &h, &rs, &interlaced, &fps_n, &fps_d, &size)) { + GST_INFO_OBJECT (v4l2src, + "can't get capture format from caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + ++ /* if necessary, update caps for rowstride */ ++ if (rs) { ++ caps = gst_v4l2_object_update_rowstride (v4l2src->v4l2object, caps, rs); ++ } ++ + GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, " + "format %s", w, h, fps_n, fps_d, format->description); + +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0009-use-GstEventCrop-to-get-crop-info.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0009-use-GstEventCrop-to-get-crop-info.patch new file mode 100644 index 0000000..8b8679e --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0009-use-GstEventCrop-to-get-crop-info.patch @@ -0,0 +1,119 @@ +From e7497b9f0c6c88b764d8f95e01197e2a2ea0dd95 Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Tue, 25 May 2010 11:02:45 -0500 +Subject: [PATCH 09/11] use GstEventCrop to get crop info + +--- + sys/v4l2/gstv4l2sink.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++- + 1 files changed, 62 insertions(+), 1 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index a1f78cf..feafe7a 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -252,6 +252,7 @@ static GstCaps *gst_v4l2sink_get_caps (GstBaseSink * bsink); + static gboolean gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps); + static GstFlowReturn gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); ++static gboolean gst_v4l2sink_event (GstBaseSink * bsink, GstEvent * event); + static GstFlowReturn gst_v4l2sink_show_frame (GstBaseSink * bsink, + GstBuffer * buf); + static void gst_v4l2sink_sync_rotation (GstV4l2Sink * v4l2sink); +@@ -354,6 +355,7 @@ gst_v4l2sink_class_init (GstV4l2SinkClass * klass) + basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_get_caps); + basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_set_caps); + basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_v4l2sink_buffer_alloc); ++ basesink_class->event = GST_DEBUG_FUNCPTR (gst_v4l2sink_event); + basesink_class->render = GST_DEBUG_FUNCPTR (gst_v4l2sink_show_frame); + } + +@@ -895,11 +897,22 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + + gst_query_parse_buffers_dimensions (query, &min_width, &min_height); + if (min_width > w) { ++ v4l2sink->crop.width = w; ++ v4l2sink->crop_fields_set |= RECT_WIDTH_SET; + w = min_width; + } + if (min_height > h) { ++ v4l2sink->crop.height = h; ++ v4l2sink->crop_fields_set |= RECT_HEIGHT_SET; + h = min_height; + } ++ ++ /* clear top/left crop values.. otherwise by default display will try ++ * to center, rather than scale, the image if it is too big to fit on ++ * display ++ */ ++ v4l2sink->crop.top = v4l2sink->crop.left = 0; ++ v4l2sink->crop_fields_set |= RECT_TOP_SET | RECT_LEFT_SET; + } + gst_query_unref (query); + +@@ -919,7 +932,13 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + GST_VIDEO_SINK_WIDTH (v4l2sink) = w; + GST_VIDEO_SINK_HEIGHT (v4l2sink) = h; + +- v4l2sink->current_caps = gst_caps_ref (caps); ++ /* this needs to go after gst_v4l2_object_set_format() to ensure driver ++ * has proper width/height (so we don't confuse it's error checking by ++ * setting a crop larger than the picture size) ++ */ ++ gst_v4l2sink_sync_crop_fields (v4l2sink); ++ ++ v4l2sink->current_caps = caps; + + return TRUE; + } +@@ -1023,6 +1042,48 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + } + } + ++/* called to handle events */ ++static gboolean ++gst_v4l2sink_event (GstBaseSink * bsink, GstEvent * event) ++{ ++ GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); ++ GstEventType type = GST_EVENT_TYPE (event); ++ ++ GST_DEBUG_OBJECT (v4l2sink, "event %" GST_PTR_FORMAT, event); ++ ++ switch (type) { ++ case GST_EVENT_CROP:{ ++ gint top, left, width, height; ++ gst_event_parse_crop (event, &top, &left, &width, &height); ++ if (top >= 0) { ++ v4l2sink->crop.top = top; ++ v4l2sink->crop_fields_set |= RECT_TOP_SET; ++ } ++ if (left >= 0) { ++ v4l2sink->crop.left = left; ++ v4l2sink->crop_fields_set |= RECT_LEFT_SET; ++ } ++ if (width >= 0) { ++ v4l2sink->crop.width = width; ++ v4l2sink->crop_fields_set |= RECT_WIDTH_SET; ++ } ++ if (height >= 0) { ++ v4l2sink->crop.height = height; ++ v4l2sink->crop_fields_set |= RECT_HEIGHT_SET; ++ } ++ gst_v4l2sink_sync_crop_fields (v4l2sink); ++ return TRUE; ++ } ++ default:{ ++ if (GST_BASE_SINK_CLASS (parent_class)->event) { ++ return GST_BASE_SINK_CLASS (parent_class)->event (bsink, event); ++ } else { ++ return TRUE; ++ } ++ } ++ } ++} ++ + /* called after A/V sync to render frame */ + static GstFlowReturn + gst_v4l2sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0010-v4l2-prefer-NV12.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0010-v4l2-prefer-NV12.patch new file mode 100644 index 0000000..d47ef9a --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0010-v4l2-prefer-NV12.patch @@ -0,0 +1,28 @@ +From 107c18830342c69229857f968dff33071d07992d Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Tue, 14 Sep 2010 07:44:01 -0500 +Subject: [PATCH 10/11] v4l2: prefer NV12 + +All else being equal, the buffer sizes are smaller compared to a 422 format +like YUY2/UYVY.. although ideally rank would come from driver. +--- + sys/v4l2/gstv4l2object.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/sys/v4l2/gstv4l2object.c b/sys/v4l2/gstv4l2object.c +index 5e34456..644edcf 100644 +--- a/sys/v4l2/gstv4l2object.c ++++ b/sys/v4l2/gstv4l2object.c +@@ -886,6 +886,9 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt) + break; + + case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */ ++ rank = YUV_BASE_RANK + 11; ++ break; ++ + case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */ + case V4L2_PIX_FMT_YYUV: /* 16 YUV 4:2:2 */ + case V4L2_PIX_FMT_HI240: /* 8 8-bit color */ +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0011-v4l2sink-fix-issue-seen-with-autoconvert.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0011-v4l2sink-fix-issue-seen-with-autoconvert.patch new file mode 100644 index 0000000..44c82af --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0011-v4l2sink-fix-issue-seen-with-autoconvert.patch @@ -0,0 +1,49 @@ +From 4e319948c62aafd5339c38d065fd8dbfa5a09ced Mon Sep 17 00:00:00 2001 +From: Rob Clark <rob@ti.com> +Date: Thu, 13 Jan 2011 09:43:08 -0600 +Subject: [PATCH 11/11] v4l2sink: fix issue seen with autoconvert + +In this scenario _set_caps() will get called earlier than _buffer_alloc() +so we need to not override the number of buffers in the case that the +upstream element answers the query about number of requested buffers. +--- + sys/v4l2/gstv4l2sink.c | 6 ++++-- + 1 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/sys/v4l2/gstv4l2sink.c b/sys/v4l2/gstv4l2sink.c +index feafe7a..ca6ae15 100644 +--- a/sys/v4l2/gstv4l2sink.c ++++ b/sys/v4l2/gstv4l2sink.c +@@ -881,6 +881,8 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + + gst_query_parse_buffers_count (query, &min_buffers); + ++ GST_DEBUG_OBJECT (v4l2sink, "min_buffers=%d", min_buffers); ++ + /* XXX need to account for some buffers used by queue, etc.. probably + * queue should handle query, pass on to sink pad, and then add some + * number of buffers to the min, so this value is dynamic depending +@@ -888,10 +890,10 @@ gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) + */ + if (min_buffers != -1) { + min_buffers += 3 + v4l2sink->min_queued_bufs; ++ v4l2sink->num_buffers_can_change = FALSE; + } + + if (min_buffers > v4l2sink->num_buffers) { +- v4l2sink->num_buffers_can_change = FALSE; + v4l2sink->num_buffers = min_buffers; + } + +@@ -972,7 +974,7 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + * than four buffers: + */ + if (!strcmp ("omap_vout", driver)) { +- if (v4l2sink->num_buffers > 4) { ++ if (v4l2sink->num_buffers_can_change && v4l2sink->num_buffers > 4) { + v4l2sink->num_buffers = 4; + GST_DEBUG_OBJECT (v4l2sink, + "limiting to 4 buffers to work-around omap_vout driver bug"); +-- +1.7.0.4 + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0012-v4l2sink-Add-Userptr-support.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0012-v4l2sink-Add-Userptr-support.patch new file mode 100755 index 0000000..bed7c4e --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0012-v4l2sink-Add-Userptr-support.patch @@ -0,0 +1,440 @@ +diff -Npru gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2sink.c gst-plugins-good-0.10.27/sys/v4l2/gstv4l2sink.c +--- gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2sink.c 2011-11-03 12:15:30.899616681 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/gstv4l2sink.c 2011-11-03 12:29:07.527616613 +0530 +@@ -62,6 +62,7 @@ + + #include "gstv4l2sink.h" + #include "gst/gst-i18n-plugin.h" ++#include "gstv4l2_userpointer.h" + + #include <string.h> + +@@ -92,6 +93,7 @@ enum + PROP_CROP_HEIGHT, + PROP_ROTATION, + PROP_FLIP, ++ PROP_USERPOINTER, + }; + + +@@ -352,6 +354,11 @@ gst_v4l2sink_class_init (GstV4l2SinkClas + "Flip horizontal/vertical", + GST_TYPE_V4L2_FLIP, FLIP_NONE, G_PARAM_READWRITE)); + ++ g_object_class_install_property (gobject_class, PROP_USERPOINTER, ++ g_param_spec_boolean("userpointer", "User Pointer", ++ "configures using user pointer for display without memcopy", ++ TRUE, G_PARAM_READWRITE)); ++ + basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_get_caps); + basesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_v4l2sink_set_caps); + basesink_class->buffer_alloc = GST_DEBUG_FUNCPTR (gst_v4l2sink_buffer_alloc); +@@ -386,6 +393,8 @@ gst_v4l2sink_init (GstV4l2Sink * v4l2sin + v4l2sink->state = 0; + v4l2sink->rotation = 0; + v4l2sink->flip = FLIP_NONE; ++ v4l2sink->gst_buf_array = NULL; ++ v4l2sink->enableUserPtr = TRUE; + } + + static void +@@ -640,6 +649,9 @@ gst_v4l2sink_set_property (GObject * obj + v4l2sink->flip = g_value_get_enum (value); + gst_v4l2sink_sync_flip (v4l2sink); + break; ++ case PROP_USERPOINTER: ++ v4l2sink->enableUserPtr = g_value_get_boolean (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -693,6 +705,9 @@ gst_v4l2sink_get_property (GObject * obj + case PROP_FLIP: + g_value_set_enum (value, v4l2sink->flip); + break; ++ case PROP_USERPOINTER: ++ g_value_set_boolean (value, v4l2sink->enableUserPtr); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -705,6 +720,7 @@ gst_v4l2sink_change_state (GstElement * + { + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstV4l2Sink *v4l2sink = GST_V4L2SINK (element); ++ gint i = 0; + + GST_DEBUG_OBJECT (v4l2sink, "%d -> %d", + GST_STATE_TRANSITION_CURRENT (transition), +@@ -718,11 +734,30 @@ gst_v4l2sink_change_state (GstElement * + gst_v4l2sink_sync_rotation (v4l2sink); + gst_v4l2sink_sync_flip (v4l2sink); + break; ++ case GST_STATE_CHANGE_PLAYING_TO_PAUSED: ++ break; + default: + break; + } +- +- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); ++ if(transition == GST_STATE_CHANGE_PAUSED_TO_READY){ ++ if(v4l2sink->enableUserPtr) { ++ GST_DEBUG_OBJECT (v4l2sink, "!!!!!!!!!unreference all the remaining buffers!!!!!!!!!"); ++ printf("\n!!!!!!!!!unreference all the remaining buffers!!!!!!!!!"); ++ if(v4l2sink->gst_buf_array != NULL){ ++ for(i = 0;i<v4l2sink->num_buffers;i++) { ++ if(v4l2sink->gst_buf_array[i] != NULL) { ++ gst_buffer_unref(v4l2sink->gst_buf_array[i]); ++ v4l2sink->gst_buf_array[i] = NULL; ++ } ++ } ++ } ++ } ++ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); ++ } ++ else{ ++ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); ++ } ++ + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: +@@ -734,9 +769,14 @@ gst_v4l2sink_change_state (GstElement * + } + break; + case GST_STATE_CHANGE_READY_TO_NULL: +- if (NULL != v4l2sink->pool) ++ if (NULL != v4l2sink->pool){ + gst_v4l2_buffer_pool_destroy (v4l2sink->pool); + v4l2sink->pool = NULL; ++ } ++ if(v4l2sink->gst_buf_array){ ++ gst_v4l2sink_userpointer_deinit(v4l2sink); ++ } ++ + /* close the device */ + if (!gst_v4l2_object_stop (v4l2sink->v4l2object)) + return GST_STATE_CHANGE_FAILURE; +@@ -871,6 +911,18 @@ gst_v4l2sink_set_caps (GstBaseSink * bsi + gst_caps_unref (caps); + return FALSE; + } ++ if (v4l2sink->gst_buf_array) { ++ /* TODO: if we've already allocated buffers, we probably need to ++ * do something here to free and reallocate.... ++ * ++ * gst_v4l2_object_stop_streaming() ++ * gst_v4l2_buffer_pool_destroy() ++ * ++ */ ++ GST_DEBUG_OBJECT (v4l2sink, "warning, changing caps not supported yet"); ++ gst_caps_unref (caps); ++ return FALSE; ++ } + + /* query to find if anyone upstream using these buffers has any + * minimum requirements: +@@ -1092,11 +1144,13 @@ gst_v4l2sink_show_frame (GstBaseSink * b + { + GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); + GstBuffer *newbuf = NULL; ++ gint retval = 0; + + GST_DEBUG_OBJECT (v4l2sink, "render buffer: %p", buf); + +- if (!GST_IS_V4L2_BUFFER (buf)) { +- GstFlowReturn ret; ++ if(!v4l2sink->enableUserPtr){ ++ if (!GST_IS_V4L2_BUFFER (buf)) { ++ GstFlowReturn ret; + + /* special case check for sub-buffers: In certain cases, places like + * GstBaseTransform, which might check that the buffer is writable +@@ -1175,7 +1229,37 @@ gst_v4l2sink_show_frame (GstBaseSink * b + gst_buffer_unref (GST_BUFFER (v4l2buf)); + } + } ++ } ++ else { ++ /*configures the v4l2 to user pointer mode only once*/ ++ if(v4l2sink->gst_buf_array == NULL) { ++ v4l2sink->state = STATE_PENDING_STREAMON; ++ /*Initializes the driver to use userpointers*/ ++ retval = gst_v4l2sink_userpointer_init(bsink,v4l2sink); ++ if(retval > 0) { ++ GST_DEBUG_OBJECT (v4l2sink, "succeess fully initialized the driver for user pointer mode"); ++ } ++ else { ++ GST_DEBUG_OBJECT (v4l2sink, "failed to initialized the driver for user pointer mode"); ++ } ++ } ++ ++ /*Enqueues the buffer with v4l2*/ ++ gst_v4l2sink_enqueue_userpointer(v4l2sink,buf); ++ ++ if (v4l2sink->state == STATE_PENDING_STREAMON) { ++ GST_DEBUG_OBJECT (v4l2sink, "Start streaming"); ++ if (!gst_v4l2_object_start_streaming (v4l2sink->v4l2object)) { ++ GST_DEBUG_OBJECT (v4l2sink, "Failed to Start streaming"); ++ return GST_FLOW_ERROR; ++ } ++ v4l2sink->state = STATE_STREAMING; ++ } ++ ++ /*Dequeues the previous buffer from v4l2*/ ++ gst_v4l2sink_dequeue_userpointer(v4l2sink,v4l2sink->min_queued_bufs); + ++ } + return GST_FLOW_OK; + } + +diff -Npru gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2sink.h gst-plugins-good-0.10.27/sys/v4l2/gstv4l2sink.h +--- gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2sink.h 2011-11-03 12:14:31.347616465 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/gstv4l2sink.h 2011-11-03 12:29:07.527616613 +0530 +@@ -78,6 +78,9 @@ struct _GstV4l2Sink { + guint8 state; + gint rotation; + gint flip; ++ GstBuffer **gst_buf_array; ++ gint queued_buff_count; ++ gboolean enableUserPtr; + }; + + struct _GstV4l2SinkClass { +diff -Npru gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2_userpointer.c gst-plugins-good-0.10.27/sys/v4l2/gstv4l2_userpointer.c +--- gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2_userpointer.c 1970-01-01 05:30:00.000000000 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/gstv4l2_userpointer.c 2011-11-03 12:46:39.599616724 +0530 +@@ -0,0 +1,130 @@ ++#ifdef HAVE_CONFIG_H ++#include <config.h> ++#endif ++ ++ ++#include "gstv4l2colorbalance.h" ++#ifdef HAVE_XVIDEO ++#include "gstv4l2xoverlay.h" ++#endif ++#include "gstv4l2vidorient.h" ++ ++#include "gstv4l2sink.h" ++#include "gst/gst-i18n-plugin.h" ++ ++#include <string.h> ++#include "gstv4l2_userpointer.h" ++ ++gint ++gst_v4l2sink_userpointer_init(GstBaseSink * bsink,GstV4l2Sink * v4l2sink) ++{ ++ ++ gint retval = 0,i =0; ++ struct v4l2_requestbuffers reqbuf = {0}; ++ ++ if(v4l2sink->gst_buf_array == NULL) { ++ memset (&reqbuf, 0, sizeof (struct v4l2_requestbuffers)); ++ reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ reqbuf.count = v4l2sink->num_buffers; ++ reqbuf.memory = V4L2_MEMORY_USERPTR; ++ ++ if ((retval = v4l2_ioctl(v4l2sink->v4l2object->video_fd, VIDIOC_REQBUFS, &reqbuf))) { ++ GST_DEBUG_OBJECT (v4l2sink, "ioctl for VIDIOC_REQBUFS FAILED"); ++ switch(errno) { ++ case EBUSY: ++ GST_DEBUG_OBJECT (v4l2sink, "Error : EBUSY"); ++ break; ++ case EINVAL: ++ GST_DEBUG_OBJECT (v4l2sink, "Error : EINVAL"); ++ break; ++ default: ++ GST_DEBUG_OBJECT (v4l2sink, "Error : unknown error"); ++ break; ++ }// switch ++ } // if ..ioctl.. ++ ++ v4l2sink->queued_buff_count = 0; ++ /* allocate a gst buffer array to hold the buffers given to v4l2 for display */ ++ v4l2sink->gst_buf_array = (GstBuffer **)malloc(sizeof(GstBuffer *)* (v4l2sink->num_buffers)); ++ for(i =0; i<v4l2sink->num_buffers;i++) { ++ v4l2sink->gst_buf_array[i] = NULL; ++ } ++ } ++ else { ++ GST_DEBUG_OBJECT (v4l2sink, "Driver is already initialized"); ++ } ++ return 1; ++} ++ ++void ++gst_v4l2sink_enqueue_userpointer(GstV4l2Sink * v4l2sink,GstBuffer * buf) ++{ ++ ++ gint i=0; ++ struct v4l2_buffer v4l2buffer = {0}; ++ ++ for(i =0; i<v4l2sink->num_buffers;i++) { ++ if(v4l2sink->gst_buf_array[i] == NULL) { ++ v4l2sink->gst_buf_array[i] = buf; ++ break; ++ } ++ } ++ ++ v4l2buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ v4l2buffer.memory = V4L2_MEMORY_USERPTR; ++ v4l2buffer.m.userptr = (unsigned long)GST_BUFFER_DATA(buf); ++ v4l2buffer.length = GST_BUFFER_SIZE(buf); ++ v4l2buffer.index = i; ++ ++ if (v4l2_ioctl (v4l2sink->v4l2object->video_fd, VIDIOC_QBUF, &v4l2buffer) < 0) { ++ GST_DEBUG_OBJECT (v4l2sink, "Queuing user buffer %p with v4l2 driver failed",buf); ++ v4l2sink->gst_buf_array[i] = NULL; ++ } ++ else { ++ GST_DEBUG_OBJECT (v4l2sink, "Queued user buffer %p with v4l2 driver",buf); ++ v4l2sink->queued_buff_count++; ++ /* add reference to the corresponding gst buffer so that upstream plugin ++ does not overwrites it while displaying */ ++ gst_buffer_ref (buf); ++ } ++} ++ ++void ++gst_v4l2sink_dequeue_userpointer(GstV4l2Sink * v4l2sink, int min_queue_count) ++{ ++ struct v4l2_buffer buffer = {0}; ++ memset (&buffer, 0x00, sizeof (buffer)); ++ buffer.type = V4L2_BUF_TYPE_VIDEO_OUTPUT; ++ buffer.memory = V4L2_MEMORY_USERPTR; ++ ++ while(v4l2sink->queued_buff_count > min_queue_count) { ++ if(v4l2_ioctl (v4l2sink->v4l2object->video_fd, VIDIOC_DQBUF, &buffer) >= 0) { ++ GST_DEBUG_OBJECT (v4l2sink, "Dequeued the buffer: %p",v4l2sink->gst_buf_array[buffer.index]); ++ v4l2sink->queued_buff_count--; ++ /* unreference the corresponding gst buffer so that upstream plugin can access */ ++ if(v4l2sink->gst_buf_array[buffer.index]) ++ gst_buffer_unref(v4l2sink->gst_buf_array[buffer.index]); ++ ++ v4l2sink->gst_buf_array[buffer.index] = NULL; ++ } ++ else { ++ GST_DEBUG_OBJECT (v4l2sink, "Failed to dequeue the buffer"); ++ break; ++ } ++ } ++} ++ ++void ++gst_v4l2sink_userpointer_deinit(GstV4l2Sink * v4l2sink) ++{ ++ ++ if(v4l2sink->gst_buf_array) { ++ GST_DEBUG_OBJECT (v4l2sink, "Freeing the gst_buf_array"); ++ gst_v4l2sink_dequeue_userpointer(v4l2sink, 0); ++ free(v4l2sink->gst_buf_array); ++ v4l2sink->gst_buf_array = NULL; ++ } ++ ++} ++ ++ +diff -Npru gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2_userpointer.h gst-plugins-good-0.10.27/sys/v4l2/gstv4l2_userpointer.h +--- gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/gstv4l2_userpointer.h 1970-01-01 05:30:00.000000000 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/gstv4l2_userpointer.h 2011-11-03 12:18:32.587616929 +0530 +@@ -0,0 +1,20 @@ ++#ifndef GSTV4L2SINK_USERPTR_H ++#define GSTV4L2SINK_USERPTR_H ++ ++#include <gst/video/gstvideosink.h> ++#include <gstv4l2object.h> ++#include <gstv4l2bufferpool.h> ++#include"gstv4l2sink.h" ++#include <stdlib.h> ++ ++ ++gint ++gst_v4l2sink_userpointer_init(GstBaseSink * ,GstV4l2Sink *); ++void ++gst_v4l2sink_enqueue_userpointer(GstV4l2Sink * ,GstBuffer * ); ++void ++gst_v4l2sink_dequeue_userpointer(GstV4l2Sink * , int ); ++void ++gst_v4l2sink_userpointer_deinit(GstV4l2Sink * ); ++ ++#endif +diff -Npru gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/Makefile.am gst-plugins-good-0.10.27/sys/v4l2/Makefile.am +--- gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/Makefile.am 2011-01-02 17:10:29.000000000 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/Makefile.am 2011-11-03 12:29:12.103616704 +0530 +@@ -20,7 +20,8 @@ libgstvideo4linux2_la_SOURCES = gstv4l2. + $(xv_source) + + if BUILD_EXPERIMENTAL +-libgstvideo4linux2_la_SOURCES += gstv4l2sink.c ++libgstvideo4linux2_la_SOURCES += gstv4l2sink.c \ ++ gstv4l2_userpointer.c + endif + + libgstvideo4linux2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ +@@ -49,6 +50,7 @@ noinst_HEADERS = \ + gstv4l2bufferpool.h \ + gstv4l2colorbalance.h \ + gstv4l2object.h \ ++ gstv4l2_userpointer.h \ + gstv4l2sink.h \ + gstv4l2src.h \ + gstv4l2tuner.h \ +diff -Npru gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/Makefile.in gst-plugins-good-0.10.27/sys/v4l2/Makefile.in +--- gst-plugins-good-0.10.27_11_patch_applied/sys/v4l2/Makefile.in 2011-01-21 15:59:42.000000000 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/Makefile.in 2011-11-03 12:29:12.103616704 +0530 +@@ -35,7 +35,7 @@ PRE_UNINSTALL = : + POST_UNINSTALL = : + build_triplet = @build@ + host_triplet = @host@ +-@BUILD_EXPERIMENTAL_TRUE@am__append_1 = gstv4l2sink.c ++@BUILD_EXPERIMENTAL_TRUE@am__append_1 = gstv4l2sink.c gstv4l2_userpointer.c + subdir = sys/v4l2 + DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +@@ -116,11 +116,11 @@ libgstvideo4linux2_la_DEPENDENCIES = $(a + am__libgstvideo4linux2_la_SOURCES_DIST = gstv4l2.c \ + gstv4l2colorbalance.c gstv4l2object.c gstv4l2bufferpool.c \ + gstv4l2src.c gstv4l2tuner.c gstv4l2vidorient.c v4l2_calls.c \ +- v4l2src_calls.c gstv4l2xoverlay.c gstv4l2sink.c ++ v4l2src_calls.c gstv4l2xoverlay.c gstv4l2sink.c gstv4l2_userpointer.c + @USE_XVIDEO_TRUE@am__objects_1 = \ + @USE_XVIDEO_TRUE@ libgstvideo4linux2_la-gstv4l2xoverlay.lo + @BUILD_EXPERIMENTAL_TRUE@am__objects_2 = \ +-@BUILD_EXPERIMENTAL_TRUE@ libgstvideo4linux2_la-gstv4l2sink.lo ++@BUILD_EXPERIMENTAL_TRUE@ libgstvideo4linux2_la-gstv4l2sink.lo libgstvideo4linux2_la-gstv4l2_userpointer.lo + am_libgstvideo4linux2_la_OBJECTS = libgstvideo4linux2_la-gstv4l2.lo \ + libgstvideo4linux2_la-gstv4l2colorbalance.lo \ + libgstvideo4linux2_la-gstv4l2object.lo \ +@@ -524,6 +524,7 @@ noinst_HEADERS = \ + gstv4l2bufferpool.h \ + gstv4l2colorbalance.h \ + gstv4l2object.h \ ++ gstv4l2_userpointer.h \ + gstv4l2sink.h \ + gstv4l2src.h \ + gstv4l2tuner.h \ +@@ -617,6 +618,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2xoverlay.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-v4l2_calls.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-v4l2src_calls.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstvideo4linux2_la-gstv4l2_userpointer.Plo@am__quote@ + + .c.o: + @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@@ -730,6 +732,15 @@ libgstvideo4linux2_la-gstv4l2sink.lo: gs + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2sink.lo `test -f 'gstv4l2sink.c' || echo '$(srcdir)/'`gstv4l2sink.c + ++libgstvideo4linux2_la-gstv4l2_userpointer.lo: gstv4l2_userpointer.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -MT libgstvideo4linux2_la-gstv4l2_userpointer.lo -MD -MP -MF $(DEPDIR)/libgstvideo4linux2_la-gstv4l2_userpointer.Tpo -c -o libgstvideo4linux2_la-gstv4l2_userpointer.lo `test -f 'gstv4l2_userpointer.c' || echo '$(srcdir)/'`gstv4l2_userpointer.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstvideo4linux2_la-gstv4l2_userpointer.Tpo $(DEPDIR)/libgstvideo4linux2_la-gstv4l2_userpointer.Plo ++@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='gstv4l2_userpointer.c' object='libgstvideo4linux2_la-gstv4l2_userpointer.lo' libtool=yes @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(libgstvideo4linux2_la_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstvideo4linux2_la_CFLAGS) $(CFLAGS) -c -o libgstvideo4linux2_la-gstv4l2_userpointer.lo `test -f 'gstv4l2_userpointer.c' || echo '$(srcdir)/'`gstv4l2_userpointer.c ++ ++ + mostlyclean-libtool: + -rm -f *.lo + diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0013-v4l2sink-interlaced-seq-tb-format.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0013-v4l2sink-interlaced-seq-tb-format.patch new file mode 100644 index 0000000..1c32f15 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0013-v4l2sink-interlaced-seq-tb-format.patch @@ -0,0 +1,38 @@ +diff -Npru gst-plugins-good-0.10.27.orig/sys/v4l2/gstv4l2object.c gst-plugins-good-0.10.27/sys/v4l2/gstv4l2object.c +--- gst-plugins-good-0.10.27.orig/sys/v4l2/gstv4l2object.c 2011-11-04 16:37:53.000000000 +0530 ++++ gst-plugins-good-0.10.27/sys/v4l2/gstv4l2object.c 2011-10-25 15:48:58.000000000 +0530 +@@ -1741,7 +1741,7 @@ return_data: + s = gst_structure_copy (template); + gst_structure_set (s, "width", G_TYPE_INT, (gint) width, + "height", G_TYPE_INT, (gint) height, +- "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); ++ /* "interlaced", G_TYPE_BOOLEAN, interlaced, */ NULL); + + if (G_IS_VALUE (&rates)) { + /* only change the framerate on the template when we have a valid probed new +@@ -1999,7 +1999,7 @@ default_frame_sizes: + else + gst_structure_set (tmp, "height", GST_TYPE_INT_RANGE, min_h, max_h, NULL); + +- gst_structure_set (tmp, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); ++ // gst_structure_set (tmp, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); + + gst_caps_append_structure (ret, tmp); + +@@ -2038,7 +2038,7 @@ gst_v4l2_object_get_nearest_size (GstV4l + fmt.fmt.pix.width = *width; + fmt.fmt.pix.height = *height; + fmt.fmt.pix.pixelformat = pixelformat; +- fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; ++ fmt.fmt.pix.field = V4L2_FIELD_SEQ_TB; + r = v4l2_ioctl (fd, VIDIOC_TRY_FMT, &fmt); + } + +@@ -2084,6 +2084,7 @@ gst_v4l2_object_get_nearest_size (GstV4l + case V4L2_FIELD_NONE: + *interlaced = FALSE; + break; ++ case V4L2_FIELD_SEQ_TB: + case V4L2_FIELD_INTERLACED: + case V4L2_FIELD_INTERLACED_TB: + case V4L2_FIELD_INTERLACED_BT: diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0014-v4l2src-Add-Userptr-support.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0014-v4l2src-Add-Userptr-support.patch new file mode 100755 index 0000000..459bb07 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gst-plugins-good-0.10.28/0014-v4l2src-Add-Userptr-support.patch @@ -0,0 +1,332 @@ +diff -Npru gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2bufferpool.c gst-plugins-good-0.10.28/sys/v4l2/gstv4l2bufferpool.c +--- gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2bufferpool.c 2011-03-08 19:24:35.000000000 +0530 ++++ gst-plugins-good-0.10.28/sys/v4l2/gstv4l2bufferpool.c 2012-01-06 17:30:50.399608721 +0530 +@@ -219,6 +219,41 @@ mmap_failed: + } + } + ++static GstV4l2Buffer * ++gst_v4l2_buffer_new_userptr (GstV4l2BufferPool * pool, guint index, GstCaps * caps) ++{ ++ GstV4l2Buffer *ret; ++ guint8 *data; ++ GstBuffer *buf; ++ GstPad *srcpad; ++ ++ ret = (GstV4l2Buffer *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER); ++ ++ GST_LOG_OBJECT (pool->v4l2elem, "creating buffer %u, %p in pool %p", index, ++ ret, pool); ++ ++ ret->pool = ++ (GstV4l2BufferPool *) gst_mini_object_ref (GST_MINI_OBJECT (pool)); ++ ++ ret->vbuffer.index = index; ++ ret->vbuffer.type = pool->type; ++ ret->vbuffer.memory = V4L2_MEMORY_USERPTR; ++ ++ srcpad = GST_BASE_SRC_PAD(pool->v4l2elem); ++ gst_pad_alloc_buffer(srcpad,0,GST_V4L2SRC(pool->v4l2elem)->frame_byte_size,caps,&buf); ++ data = GST_BUFFER_DATA(buf); ++ gst_buffer_unref(buf); ++ ret->vbuffer.m.userptr = (unsigned long)data; ++ ++ GST_BUFFER_DATA (ret) = data; ++ GST_BUFFER_SIZE (ret) = ret->vbuffer.length; ++ ++ GST_BUFFER_FLAG_SET (ret, GST_BUFFER_FLAG_READONLY); ++ ++ gst_buffer_set_caps (GST_BUFFER (ret), gst_caps_ref(caps)); ++ ++ return ret; ++} + + /* + * GstV4l2BufferPool: +@@ -327,13 +362,15 @@ get_v4l2_object (GstElement * v4l2elem) + * + * Returns: the new pool, use gst_v4l2_buffer_pool_destroy() to free resources + */ ++ + GstV4l2BufferPool * + gst_v4l2_buffer_pool_new (GstElement * v4l2elem, gint fd, gint num_buffers, +- GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type) ++ GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type, enum v4l2_memory mem_type) + { + GstV4l2BufferPool *pool; + gint n; + struct v4l2_requestbuffers breq; ++ GstV4l2Buffer *(*buffer_new)(GstV4l2BufferPool * pool, guint index, GstCaps * caps); + + pool = (GstV4l2BufferPool *) gst_mini_object_new (GST_TYPE_V4L2_BUFFER_POOL); + +@@ -349,7 +386,7 @@ gst_v4l2_buffer_pool_new (GstElement * v + memset (&breq, 0, sizeof (struct v4l2_requestbuffers)); + breq.type = type; + breq.count = num_buffers; +- breq.memory = V4L2_MEMORY_MMAP; ++ breq.memory = mem_type; + + if (v4l2_ioctl (fd, VIDIOC_REQBUFS, &breq) < 0) + goto reqbufs_failed; +@@ -372,10 +409,15 @@ gst_v4l2_buffer_pool_new (GstElement * v + pool->buffer_count = num_buffers; + pool->buffers = g_new0 (GstV4l2Buffer *, num_buffers); + pool->avail_buffers = g_async_queue_new (); ++ pool->mem_type = mem_type; + +- /* now, map the buffers: */ ++ if(mem_type == V4L2_MEMORY_USERPTR) ++ buffer_new = gst_v4l2_buffer_new_userptr; ++ else ++ buffer_new = gst_v4l2_buffer_new; ++ + for (n = 0; n < num_buffers; n++) { +- pool->buffers[n] = gst_v4l2_buffer_new (pool, n, caps); ++ pool->buffers[n] = buffer_new (pool, n, caps); + if (!pool->buffers[n]) + goto buffer_new_failed; + pool->num_live_buffers++; +@@ -510,6 +552,9 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2Buffer + { + GST_LOG_OBJECT (pool->v4l2elem, "enqueue pool buffer %d", buf->vbuffer.index); + ++ if(buf->vbuffer.memory == V4L2_MEMORY_USERPTR) ++ buf->vbuffer.m.userptr = (unsigned long)GST_BUFFER_DATA(buf); ++ + if (v4l2_ioctl (pool->video_fd, VIDIOC_QBUF, &buf->vbuffer) < 0) + return FALSE; + +@@ -539,7 +584,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2Buffe + + memset (&buffer, 0x00, sizeof (buffer)); + buffer.type = pool->type; +- buffer.memory = V4L2_MEMORY_MMAP; ++ buffer.memory = pool->mem_type; + + + if (v4l2_ioctl (pool->video_fd, VIDIOC_DQBUF, &buffer) >= 0) { +diff -Npru gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2bufferpool.h gst-plugins-good-0.10.28/sys/v4l2/gstv4l2bufferpool.h +--- gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2bufferpool.h 2011-03-08 19:24:35.000000000 +0530 ++++ gst-plugins-good-0.10.28/sys/v4l2/gstv4l2bufferpool.h 2012-01-06 16:27:51.691608198 +0530 +@@ -64,6 +64,7 @@ struct _GstV4l2BufferPool + gint video_fd; /* a dup(2) of the v4l2object's video_fd */ + guint buffer_count; + GstV4l2Buffer **buffers; ++ enum v4l2_memory mem_type; + }; + + struct _GstV4l2Buffer { +@@ -79,7 +80,7 @@ struct _GstV4l2Buffer { + }; + + void gst_v4l2_buffer_pool_destroy (GstV4l2BufferPool * pool); +-GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type); ++GstV4l2BufferPool *gst_v4l2_buffer_pool_new (GstElement *v4l2elem, gint fd, gint num_buffers, GstCaps * caps, gboolean requeuebuf, enum v4l2_buf_type type, enum v4l2_memory mem_type); + + + GstV4l2Buffer *gst_v4l2_buffer_pool_get (GstV4l2BufferPool *pool, gboolean blocking); +diff -Npru gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2object.c gst-plugins-good-0.10.28/sys/v4l2/gstv4l2object.c +--- gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2object.c 2012-01-04 14:41:22.979611574 +0530 ++++ gst-plugins-good-0.10.28/sys/v4l2/gstv4l2object.c 2012-01-06 16:27:51.735609396 +0530 +@@ -40,7 +40,8 @@ + #include "gstv4l2colorbalance.h" + + #include "gst/gst-i18n-plugin.h" +- ++#include "gstv4l2src.h" ++#include "gstv4l2sink.h" + /* videodev2.h is not versioned and we can't easily check for the presence + * of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define + * was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */ +@@ -1510,7 +1511,8 @@ gst_v4l2_object_get_caps_info (GstV4l2Ob + fmt.fmt.pix.bytesperline = *rs; + if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_TRY_FMT, &fmt) >= 0) { + if (fmt.fmt.pix.bytesperline == *rs) { +- *rs = 0; ++ if (GST_IS_V4L2SINK (v4l2object->element)) ++ *rs = 0; + } else { + *rs = fmt.fmt.pix.bytesperline; + } +diff -Npru gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2sink.c gst-plugins-good-0.10.28/sys/v4l2/gstv4l2sink.c +--- gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2sink.c 2012-01-04 14:41:22.967609512 +0530 ++++ gst-plugins-good-0.10.28/sys/v4l2/gstv4l2sink.c 2012-01-06 16:27:51.739609397 +0530 +@@ -1046,7 +1046,7 @@ gst_v4l2sink_buffer_alloc (GstBaseSink * + if (!(v4l2sink->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2sink), + v4l2sink->v4l2object->video_fd, + v4l2sink->num_buffers, caps, FALSE, +- V4L2_BUF_TYPE_VIDEO_OUTPUT))) { ++ V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_MEMORY_MMAP))) { + return GST_FLOW_ERROR; + } + +diff -Npru gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2src.c gst-plugins-good-0.10.28/sys/v4l2/gstv4l2src.c +--- gst-plugins-good-0.10.28.orig/sys/v4l2/gstv4l2src.c 2012-01-04 14:41:22.879611204 +0530 ++++ gst-plugins-good-0.10.28/sys/v4l2/gstv4l2src.c 2012-01-06 17:29:28.836112240 +0530 +@@ -216,6 +216,10 @@ gst_v4l2src_get_read (GstV4l2Src * v4l2s + static GstFlowReturn + gst_v4l2src_get_mmap (GstV4l2Src * v4l2src, GstBuffer ** buf); + ++/* DV query method */ ++void gst_v4l2_object_set_dv_preset(GstV4l2Object * v4l2object); ++ ++ + static void + gst_v4l2src_base_init (gpointer g_class) + { +@@ -608,6 +612,33 @@ gst_v4l2src_get_caps (GstBaseSrc * src) + return ret; + } + ++void gst_v4l2_object_set_dv_preset(GstV4l2Object * v4l2object) ++{ ++ struct v4l2_dv_preset dv_preset; ++ ++ dv_preset.preset = 0x0; ++ v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERY_DV_PRESET, &dv_preset); ++ ++ switch (dv_preset.preset) { ++ case V4L2_DV_720P60: ++ printf("\n Mode set is 720P60\n"); ++ break; ++ case V4L2_DV_1080I60: ++ printf("\n Mode set is 1080I60\n"); ++ break; ++ case V4L2_DV_1080P60: ++ printf("\n Mode set is 1080P60\n"); ++ break; ++ case V4L2_DV_1080P30: ++ printf("\n Mode set is 1080P30\n"); ++ break; ++ default: ++ printf("\n Mode set is %d\n", dv_preset.preset); ++ } ++ v4l2_ioctl (v4l2object->video_fd, VIDIOC_S_DV_PRESET, &dv_preset); ++ ++} ++ + static gboolean + gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) + { +@@ -633,6 +664,7 @@ gst_v4l2src_set_caps (GstBaseSrc * src, + return FALSE; + } + ++ gst_v4l2_object_set_dv_preset(v4l2src->v4l2object); + /* we want our own v4l2 type of fourcc codes */ + if (!gst_v4l2_object_get_caps_info (v4l2src->v4l2object, caps, &format, + &w, &h, &rs, &interlaced, &fps_n, &fps_d, &size)) { +@@ -649,6 +681,9 @@ gst_v4l2src_set_caps (GstBaseSrc * src, + GST_DEBUG_OBJECT (v4l2src, "trying to set_capture %dx%d at %d/%d fps, " + "format %s", w, h, fps_n, fps_d, format->description); + ++ /* now store the expected output size */ ++ v4l2src->frame_byte_size = size; ++ + if (!gst_v4l2src_set_capture (v4l2src, format->pixelformat, w, h, + interlaced, fps_n, fps_d)) + /* error already posted */ +@@ -666,9 +701,6 @@ gst_v4l2src_set_caps (GstBaseSrc * src, + if (!gst_v4l2src_capture_start (v4l2src)) + return FALSE; + +- /* now store the expected output size */ +- v4l2src->frame_byte_size = size; +- + return TRUE; + } + +@@ -901,9 +933,7 @@ gst_v4l2src_get_mmap (GstV4l2Src * v4l2s + GstBuffer *temp; + GstFlowReturn ret; + guint size; +- guint count = 0; + +-again: + ret = gst_v4l2src_grab_frame (v4l2src, &temp); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto done; +@@ -911,31 +941,13 @@ again: + if (v4l2src->frame_byte_size > 0) { + size = GST_BUFFER_SIZE (temp); + +- /* if size does not match what we expected, try again */ +- if (size != v4l2src->frame_byte_size) { +- GST_ELEMENT_WARNING (v4l2src, RESOURCE, READ, +- (_("Got unexpected frame size of %u instead of %u."), +- size, v4l2src->frame_byte_size), (NULL)); +- gst_buffer_unref (temp); +- if (count++ > 50) +- goto size_error; +- +- goto again; +- } ++ if (size != v4l2src->frame_byte_size) ++ GST_BUFFER_SIZE (temp) = v4l2src->frame_byte_size; + } + + *buf = temp; + done: + return ret; +- +- /* ERRORS */ +-size_error: +- { +- GST_ELEMENT_ERROR (v4l2src, RESOURCE, READ, +- (_("Error reading %d bytes on device '%s'."), +- v4l2src->frame_byte_size, v4l2src->v4l2object->videodev), (NULL)); +- return GST_FLOW_ERROR; +- } + } + + static GstFlowReturn +diff -Npru gst-plugins-good-0.10.28.orig/sys/v4l2/v4l2src_calls.c gst-plugins-good-0.10.28/sys/v4l2/v4l2src_calls.c +--- gst-plugins-good-0.10.28.orig/sys/v4l2/v4l2src_calls.c 2011-03-08 19:24:35.000000000 +0530 ++++ gst-plugins-good-0.10.28/sys/v4l2/v4l2src_calls.c 2012-01-06 16:27:51.743610680 +0530 +@@ -110,6 +110,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l + GST_DEBUG_OBJECT (v4l2src, "grab frame"); + + for (;;) { ++#if 0 + if (v4l2object->can_poll_device) { + ret = gst_poll_wait (v4l2object->poll, GST_CLOCK_TIME_NONE); + if (G_UNLIKELY (ret < 0)) { +@@ -125,7 +126,7 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l + } + } + } +- ++#endif + pool_buffer = GST_BUFFER (gst_v4l2_buffer_pool_dqbuf (pool)); + if (pool_buffer) + break; +@@ -163,15 +164,18 @@ gst_v4l2src_grab_frame (GstV4l2Src * v4l + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, v4l2src, + "running out of buffers, making a copy to reuse current one"); + } ++#if 0 + *buf = gst_buffer_copy (pool_buffer); + GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); + /* this will requeue */ + gst_buffer_unref (pool_buffer); ++#else ++ *buf = pool_buffer; ++#endif + } else { + *buf = pool_buffer; + } + /* we set the buffer metadata in gst_v4l2src_create() */ +- + return GST_FLOW_OK; + + /* ERRORS */ +@@ -309,7 +313,7 @@ gst_v4l2src_capture_init (GstV4l2Src * v + + if (!(v4l2src->pool = gst_v4l2_buffer_pool_new (GST_ELEMENT (v4l2src), + v4l2src->v4l2object->video_fd, +- v4l2src->num_buffers, caps, TRUE, V4L2_BUF_TYPE_VIDEO_CAPTURE))) ++ v4l2src->num_buffers, caps, TRUE, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_MEMORY_USERPTR))) + goto buffer_pool_new_failed; + + GST_INFO_OBJECT (v4l2src, "capturing buffers via mmap()"); diff --git a/gstreamer_ti_dm81xx/opensource_build/patchfiles/gstreamer-0.10.32/0006-queue-free-erroneous-buffer.patch b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gstreamer-0.10.32/0006-queue-free-erroneous-buffer.patch new file mode 100644 index 0000000..1b33670 --- /dev/null +++ b/gstreamer_ti_dm81xx/opensource_build/patchfiles/gstreamer-0.10.32/0006-queue-free-erroneous-buffer.patch @@ -0,0 +1,12 @@ +--- gstreamer-0.10.32.orig/plugins/elements/gstqueue.c 2011-01-06 22:45:35.000000000 +0530 ++++ gstreamer-0.10.32/plugins/elements/gstqueue.c 2011-11-18 17:35:40.431361170 +0530 +@@ -1173,7 +1173,8 @@ next: + * task function does not shut down. */ + queue->unexpected = TRUE; + result = GST_FLOW_OK; +- } ++ }else if(result == GST_FLOW_WRONG_STATE) ++ gst_buffer_unref (buffer); + } else { + GstEvent *event = GST_EVENT_CAST (data); + GstEventType type = GST_EVENT_TYPE (event); diff --git a/gstreamer_ti_dm81xx/ti_build/Makefile b/gstreamer_ti_dm81xx/ti_build/Makefile index c1a79f2..8a3a5f2 100644 --- a/gstreamer_ti_dm81xx/ti_build/Makefile +++ b/gstreamer_ti_dm81xx/ti_build/Makefile @@ -57,6 +57,10 @@ $(TI_PLUGINS): $(CMD_PREFIX) cd $@; ./configure $(CONFIGURE_VERBOSE) $(CC_CONFIGURE_OPTS) $(EXTRA_CONFIGURE_OPTS) $(CMD_PREFIX) $(MAKE) $(MAKE_VERBOSE) -C $@ $(BUILD_INSTALL) +my: + @echo Building gst-openmax + $(CMD_PREFIX) $(MAKE) $(MAKE_VERBOSE) -C gst-openmax $(BUILD_INSTALL) + install: clean: diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/ChangeLog b/gstreamer_ti_dm81xx/ti_build/gst-openmax/ChangeLog index 5d7d986..0f62f6a 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/ChangeLog +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/ChangeLog @@ -1,3 +1,9 @@ +== TI Gstreamer Plugin Release 0.3 == + +* Initial Public Release of the TI GStreamer DM81xx Plugin. +* Adapted from GST-OpenMAX by Felipe Contreras <felipe.contreras@gmail.com> +* Supports TI OMX libraries + == Release 0.10.0.4 == 2008-06-19 Felipe Contreras <felipe.contreras@gmail.com> diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/configure.ac b/gstreamer_ti_dm81xx/ti_build/gst-openmax/configure.ac index 1ec65d0..89e3c31 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/configure.ac +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/configure.ac @@ -1,8 +1,7 @@ AC_PREREQ([2.52]) dnl AC_INIT([gst-openmax], m4_esyscmd([build-aux/git-version-gen]), -AC_INIT([gst-openmax], - [http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer&component=gst-openmax]) +AC_INIT([gst-openmax], [GST_DM81XX_00_04_00_00], [https://gstreamer.ti.com/gf/project/gstreamer_ti/forum/]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([-Wall -Wno-portability]) diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/ext/Makefile b/gstreamer_ti_dm81xx/ti_build/gst-openmax/ext/Makefile index 45953cb..c412c39 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/ext/Makefile +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/ext/Makefile @@ -26,7 +26,15 @@ all: -Wl,-u,OMX_Init -Wl,-u,OMX_Deinit -Wl,-u,OMX_ComponentNameEnum -Wl,-u,OMX_GetHandle -Wl,-u,OMX_FreeHandle \ -Wl,-u,OMX_GetRolesOfComponent +distclean: + clean: rm -rf lib install: all + +distdir: + mkdir -p $(distdir) + cp -f Makefile $(distdir) + +distclean: diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/Makefile.am b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/Makefile.am index 00ea054..de5ee7c 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/Makefile.am +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/Makefile.am @@ -3,6 +3,7 @@ plugin_LTLIBRARIES = libgstomx.la libgstomx_la_SOURCES = gstomx.c gstomx.h \ gstomx_interface.c gstomx_interface.h \ gstomx_base_filter.c gstomx_base_filter.h \ + gstomx_base_filter2.c gstomx_base_filter2.h \ gstomx_base_videodec.c gstomx_base_videodec.h \ gstomx_base_videoenc.c gstomx_base_videoenc.h \ gstomx_base_audiodec.c gstomx_base_audiodec.h \ @@ -13,9 +14,10 @@ libgstomx_la_SOURCES = gstomx.c gstomx.h \ gstomx_volume.c gstomx_volume.h \ gstomx_mpeg4dec.c gstomx_mpeg4dec.h \ gstomx_mpeg2dec.c gstomx_mpeg2dec.h \ + gstomx_mjpegdec.c gstomx_mjpegdec.h \ gstomx_h263dec.c gstomx_h263dec.h \ gstomx_h264dec.c gstomx_h264dec.h \ - gstomx_vc1dec.c gstomx_vc1dec.h \ + gstomx_vc1dec.c gstomx_vc1dec.h \ gstomx_wmvdec.c gstomx_wmvdec.h \ gstomx_mpeg4enc.c gstomx_mpeg4enc.h \ gstomx_h264enc.c gstomx_h264enc.h \ @@ -46,15 +48,18 @@ libgstomx_la_SOURCES = gstomx.c gstomx.h \ gstomx_filereadersrc.c gstomx_filereadersrc.h \ swcsc.c swcsc.h \ gstperf.c gstperf.h \ + gstomxbufferalloc.c gstomxbufferalloc.h \ gstomx_buffertransport.c gstomx_buffertransport.h \ gstomx_base_vfpc.c gstomx_base_vfpc.h \ + gstomx_base_vfpc2.c gstomx_base_vfpc2.h \ gstomx_base_ctrl.c gstomx_base_ctrl.h \ gstomx_scaler.c gstomx_scaler.h \ + gstomx_deiscaler.c gstomx_deiscaler.h \ gstomx_noisefilter.c gstomx_noisefilter.h \ gstomx_videomixer.c gstomx_videomixer.h libgstomx_la_LIBADD = $(OMXCORE_LIBS) $(GST_LIBS) $(GST_BASE_LIBS) -lgstvideo-0.10 $(top_builddir)/util/libutil.la -libgstomx_la_CFLAGS = $(OMXCORE_CFLAGS) $(OMXTIAUDIODEC_CFLAGS) $(USE_OMXTIAUDIODEC) $(GST_CFLAGS) $(GST_BASE_CFLAGS) -I$(top_srcdir)/util \ +libgstomx_la_CFLAGS = -DUSE_OMXTICORE $(OMXCORE_CFLAGS) $(OMXTIAUDIODEC_CFLAGS) $(USE_OMXTIAUDIODEC) $(GST_CFLAGS) $(GST_BASE_CFLAGS) -I$(top_srcdir)/util \ -Dxdc_target_name__=GCArmv5T -Dxdc_target_types__=gnu/targets/arm/std.h -Dxdc__RESTRICT__ \ -I$(OMX_INSTALL_DIR)/include/openMaxv11 \ -I$(OMX_INSTALL_DIR)/packages \ diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx.c index 9dc840f..e50c3e9 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx.c @@ -23,9 +23,10 @@ #include "gstomx_dummy.h" #include "gstomx_mpeg4dec.h" #include "gstomx_mpeg2dec.h" +#include "gstomx_mjpegdec.h" #include "gstomx_h263dec.h" #include "gstomx_h264dec.h" -#include "gstomx_vp6dec.h" +// #include "gstomx_vp6dec.h" #include "gstomx_wmvdec.h" #include "gstomx_mpeg4enc.h" #include "gstomx_h264enc.h" @@ -53,15 +54,18 @@ #include "gstomx_videosink.h" #include "gstomx_filereadersrc.h" #include "gstomx_volume.h" -#include "gstomx_camera.h" +// #include "gstomx_camera.h" #include "swcsc.h" #include "gstperf.h" #include "gstomx_scaler.h" +#include "gstomx_deiscaler.h" #include "gstomx_noisefilter.h" #include "gstomx_base_ctrl.h" #include "gstomx_vc1dec.h" #include "gstomx_videomixer.h" +#include "gstomxbufferalloc.h" + #include "config.h" GST_DEBUG_CATEGORY (gstomx_debug); @@ -82,6 +86,7 @@ static TableItem element_table[] = // { "omx_dummy", "libOMX_Core.so", "OMX.TI.DUCATI1.MISC.SAMPLE", NULL, GST_RANK_NONE, gst_omx_dummy_get_type }, { "omx_mpeg4dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_mpeg4dec_get_type }, { "omx_h264dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_h264dec_get_type }, + { "omx_mjpegdec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_mjpegdec_get_type }, { "omx_mpeg2dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_mpeg2dec_get_type }, // { "omx_h263dec", "libOMX_Core.so", "OMX.TI.DUCATI.VIDDEC", "", GST_RANK_PRIMARY, gst_omx_h263dec_get_type }, // { "omx_vp6dec", "libOMX_Core.so", "OMX.TI.DUCATI1.VIDEO.DECODER", "video_decoder.vp6", GST_RANK_PRIMARY, gst_omx_vp6dec_get_type }, @@ -97,8 +102,8 @@ static TableItem element_table[] = // { "omx_amrnbenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.amrnb", NULL, GST_RANK_NONE, gst_omx_amrnbenc_get_type }, // { "omx_amrwbdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.amrwb", NULL, GST_RANK_NONE, gst_omx_amrwbdec_get_type }, // { "omx_amrwbenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.amrwb", NULL, GST_RANK_NONE, gst_omx_amrwbenc_get_type }, -// { "omx_aacdec", "libOMX_Core.so", "OMX.TI.AUDIO.DECODE", "audio_decode.dsp.aac", GST_RANK_NONE, gst_omx_aacdec_get_type }, -// { "omx_aacenc", "libOMX_Core.so", "OMX.TI.AUDIO.ENCODE", "audio_encode.dsp.aac", GST_RANK_NONE, gst_omx_aacenc_get_type }, + { "omx_aacdec", "libOMX_Core.so", "OMX.TI.DSP.AUDDEC", "", GST_RANK_PRIMARY, gst_omx_aacdec_get_type }, + { "omx_aacenc", "libOMX_Core.so", "OMX.TI.DSP.AUDENC", "", GST_RANK_PRIMARY, gst_omx_aacenc_get_type }, // { "omx_adpcmdec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.adpcm", NULL, GST_RANK_NONE, gst_omx_adpcmdec_get_type }, // { "omx_adpcmenc", "libomxil-bellagio.so.0", "OMX.st.audio_encoder.adpcm", NULL, GST_RANK_NONE, gst_omx_adpcmenc_get_type }, // { "omx_g711dec", "libomxil-bellagio.so.0", "OMX.st.audio_decoder.g711", NULL, GST_RANK_NONE, gst_omx_g711dec_get_type }, @@ -115,7 +120,10 @@ static TableItem element_table[] = // { "omx_volume", "libomxil-bellagio.so.0", "OMX.st.volume.component", NULL, GST_RANK_NONE, gst_omx_volume_get_type }, { "swcsc", "libOMX_Core.so", NULL, NULL, GST_RANK_PRIMARY, gst_swcsc_get_type }, { "gstperf", "libOMX_Core.so", NULL, NULL, GST_RANK_PRIMARY, gst_perf_get_type }, + { "omxbufferalloc", "libOMX_Core.so", NULL, NULL, GST_RANK_PRIMARY, gst_omx_buffer_alloc_get_type }, { "omx_scaler", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.INDTXSCWB", "", GST_RANK_PRIMARY, gst_omx_scaler_get_type }, + { "omx_mdeiscaler", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.DEIMDUALOUT", "", GST_RANK_PRIMARY, gst_omx_mdeiscaler_get_type }, + { "omx_hdeiscaler", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.DEIHDUALOUT", "", GST_RANK_PRIMARY, gst_omx_hdeiscaler_get_type }, { "omx_noisefilter", "libOMX_Core.so", "OMX.TI.VPSSM3.VFPC.NF", "", GST_RANK_PRIMARY, gst_omx_noisefilter_get_type }, { "omx_ctrl", "libOMX_Core.so", "OMX.TI.VPSSM3.CTRL.DC", "", GST_RANK_PRIMARY, gst_omx_base_ctrl_get_type }, // { "omx_camera", "libOMX_Core.so", "OMX.TI.DUCATI1.VIDEO.CAMERA", NULL, GST_RANK_PRIMARY, gst_omx_camera_get_type }, diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacdec.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacdec.c index 09b0cc7..9dee258 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacdec.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacdec.c @@ -29,8 +29,8 @@ enum { - ARG_0, - ARG_FRAMEMODE, + ARG_0, + ARG_FRAMEMODE, }; #define FRAMEMODE_DEFAULT FALSE @@ -39,314 +39,454 @@ GSTOMX_BOILERPLATE (GstOmxAacDec, gst_omx_aacdec, GstOmxBaseAudioDec, GST_OMX_BA typedef enum { - AAC_PROFILE_LC = 2, - AAC_PROFILE_LC_SBR = 5, - AAC_PROFILE_LC_SBR_PS = 6, + AAC_PROFILE_LC = 2, + AAC_PROFILE_LC_SBR = 5, + AAC_PROFILE_LC_SBR_PS = 6, } AacVersion; -static GstCaps * + static GstCaps * generate_src_template (void) { - GstCaps *caps; - - caps = gst_caps_new_simple ("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "rate", GST_TYPE_INT_RANGE, 8000, 96000, - "signed", G_TYPE_BOOLEAN, TRUE, - "channels", GST_TYPE_INT_RANGE, 1, 8, - NULL); - - return caps; + GstCaps *caps; + + caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "rate", GST_TYPE_INT_RANGE, 8000, 96000, + "signed", G_TYPE_BOOLEAN, TRUE, + "channels", GST_TYPE_INT_RANGE, 1, 8, + NULL); + + return caps; } -static GstCaps * + static GstCaps * generate_sink_template (void) { - GstCaps *caps; - GstStructure *struc; - caps = gst_caps_new_empty (); + GstCaps *caps; + GstStructure *struc; + caps = gst_caps_new_empty (); - struc = gst_structure_new ("audio/mpeg", - "mpegversion", G_TYPE_INT, 4, - "channels", GST_TYPE_INT_RANGE, 1, 8, - "rate", GST_TYPE_INT_RANGE, 8000, 96000, - "object_type", GST_TYPE_INT_RANGE, 1, 6, - "parsed", G_TYPE_BOOLEAN, TRUE, - NULL); + struc = gst_structure_new ("audio/mpeg", + "mpegversion", G_TYPE_INT, 4, + "channels", GST_TYPE_INT_RANGE, 1, 8, + "rate", GST_TYPE_INT_RANGE, 8000, 96000, + "object_type", GST_TYPE_INT_RANGE, 1, 6, + "parsed", G_TYPE_BOOLEAN, TRUE, + NULL); - { - GValue list; - GValue val; + { + GValue list; + GValue val; - list.g_type = val.g_type = 0; + list.g_type = val.g_type = 0; - g_value_init (&list, GST_TYPE_LIST); - g_value_init (&val, G_TYPE_INT); + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_INT); - g_value_set_int (&val, 2); - gst_value_list_append_value (&list, &val); + g_value_set_int (&val, 2); + gst_value_list_append_value (&list, &val); - g_value_set_int (&val, 4); - gst_value_list_append_value (&list, &val); + g_value_set_int (&val, 4); + gst_value_list_append_value (&list, &val); - gst_structure_set_value (struc, "mpegversion", &list); + gst_structure_set_value (struc, "mpegversion", &list); - g_value_unset (&val); - g_value_unset (&list); - } + g_value_unset (&val); + g_value_unset (&list); + } - gst_caps_append_structure (caps, struc); - - return caps; + gst_caps_append_structure (caps, struc); + return caps; } -static void + static void type_base_init (gpointer g_class) { - GstElementClass *element_class; + GstElementClass *element_class; - element_class = GST_ELEMENT_CLASS (g_class); + element_class = GST_ELEMENT_CLASS (g_class); - { - GstElementDetails details; + { + GstElementDetails details; - details.longname = "OpenMAX IL AAC audio decoder"; - details.klass = "Codec/Decoder/Audio"; - details.description = "Decodes audio in AAC format with OpenMAX IL"; - details.author = "Felipe Contreras"; + details.longname = "OpenMAX IL AAC audio decoder"; + details.klass = "Codec/Decoder/Audio"; + details.description = "Decodes audio in AAC format with OpenMAX IL"; + details.author = "Felipe Contreras"; - gst_element_class_set_details (element_class, &details); - } + gst_element_class_set_details (element_class, &details); + } - { - GstPadTemplate *template; + { + GstPadTemplate *template; - template = gst_pad_template_new ("src", GST_PAD_SRC, - GST_PAD_ALWAYS, - generate_src_template ()); + template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, + generate_src_template ()); - gst_element_class_add_pad_template (element_class, template); - } + gst_element_class_add_pad_template (element_class, template); + } - { - GstPadTemplate *template; + { + GstPadTemplate *template; - template = gst_pad_template_new ("sink", GST_PAD_SINK, - GST_PAD_ALWAYS, - generate_sink_template ()); + template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, + generate_sink_template ()); - gst_element_class_add_pad_template (element_class, template); - } + gst_element_class_add_pad_template (element_class, template); + } } -static void + static void set_property (GObject *obj, - guint prop_id, - const GValue *value, - GParamSpec *pspec) + guint prop_id, + const GValue *value, + GParamSpec *pspec) { - GstOmxAacDec *self; - - self = GST_OMX_AACDEC (obj); - - switch (prop_id) - { - case ARG_FRAMEMODE: - self->framemode = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); - break; - } + GstOmxAacDec *self; + + self = GST_OMX_AACDEC (obj); + + switch (prop_id) + { + case ARG_FRAMEMODE: + self->framemode = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } } -static void + static void get_property (GObject *obj, - guint prop_id, - GValue *value, - GParamSpec *pspec) + guint prop_id, + GValue *value, + GParamSpec *pspec) { - GstOmxAacDec *self; - - self = GST_OMX_AACDEC (obj); - - switch (prop_id) - { - case ARG_FRAMEMODE: - g_value_set_boolean (value, self->framemode); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); - break; - } + GstOmxAacDec *self; + + self = GST_OMX_AACDEC (obj); + + switch (prop_id) + { + case ARG_FRAMEMODE: + g_value_set_boolean (value, self->framemode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } } -static void + static void type_class_init (gpointer g_class, - gpointer class_data) + gpointer class_data) { - GObjectClass *gobject_class; + GObjectClass *gobject_class; - gobject_class = G_OBJECT_CLASS (g_class); + gobject_class = G_OBJECT_CLASS (g_class); - /* Properties stuff */ - { - gobject_class->set_property = set_property; - gobject_class->get_property = get_property; + /* Properties stuff */ + { + gobject_class->set_property = set_property; + gobject_class->get_property = get_property; - g_object_class_install_property (gobject_class, ARG_FRAMEMODE, - g_param_spec_boolean ("framemode", "Frame Mode", - "Frame Mode", FRAMEMODE_DEFAULT, G_PARAM_READWRITE)); - } + g_object_class_install_property (gobject_class, ARG_FRAMEMODE, + g_param_spec_boolean ("framemode", "Frame Mode", + "Frame Mode", FRAMEMODE_DEFAULT, G_PARAM_READWRITE)); + } } -static gboolean + static gboolean sink_setcaps (GstPad *pad, - GstCaps *caps) + GstCaps *caps) { - GstStructure *structure; - GstOmxBaseFilter *omx_base; - GstOmxBaseAudioDec *base_audiodec; - GstOmxAacDec* self; + GstStructure *structure; + GstOmxBaseFilter *omx_base; + GstOmxBaseAudioDec *base_audiodec; + GstOmxAacDec* self; - omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); - base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); - self = GST_OMX_AACDEC (omx_base); - GST_INFO_OBJECT (omx_base, "setcaps (sink): %" GST_PTR_FORMAT, caps); + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); + self = GST_OMX_AACDEC (omx_base); - structure = gst_caps_get_structure (caps, 0); + GST_INFO_OBJECT (omx_base, "setcaps (sink): %" GST_PTR_FORMAT, caps); - base_audiodec->rate = 44100; - gst_structure_get_int (structure, "rate", &base_audiodec->rate); + structure = gst_caps_get_structure (caps, 0); - base_audiodec->channels = 2; - gst_structure_get_int (structure, "channels", &base_audiodec->channels); - self->aacversion = 2; - gst_structure_get_int (structure, "object_type", &self->aacversion); + base_audiodec->rate = 44100; + gst_structure_get_int (structure, "rate", &base_audiodec->rate); - self->framed = gst_structure_has_field (structure, "framed"); + base_audiodec->channels = 2; + gst_structure_get_int (structure, "channels", &base_audiodec->channels); + + self->aacversion = 2; + gst_structure_get_int (structure, "object_type", &self->aacversion); + + self->framed = gst_structure_has_field (structure, "framed"); + + omx_base->in_port->caps = gst_caps_copy (caps); -#if 0 - { - const GValue *codec_data; - GstBuffer *buffer; - codec_data = gst_structure_get_value (structure, "codec_data"); - if (codec_data) - { - buffer = gst_value_get_buffer (codec_data); - omx_base->codec_data = buffer; - gst_buffer_ref (buffer); - } - } -#endif - return gst_pad_set_caps (pad, caps); + return gst_pad_set_caps (pad, caps); } + static gboolean +src_setcaps (GstPad *pad, + GstCaps *caps) +{ + GstStructure *structure; + GstOmxBaseFilter *omx_base; + GstOmxBaseAudioDec *base_audiodec; + GstOmxAacDec* self; -static void -omx_setup (GstOmxBaseFilter *omx_base) + + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); + self = GST_OMX_AACDEC (omx_base); + + GST_INFO_OBJECT (omx_base, "setcaps (sink): %" GST_PTR_FORMAT, caps); + + structure = gst_caps_get_structure (caps, 0); + + + base_audiodec->rate = 44100; + //gst_structure_get_int (structure, "rate", &base_audiodec->rate); + + base_audiodec->channels = 2; + //gst_structure_get_int (structure, "channels", &base_audiodec->channels); + + self->aacversion = 2; + //gst_structure_get_int (structure, "object_type", &self->aacversion); + + self->framed = gst_structure_has_field (structure, "framed"); + + omx_base->out_port->caps = gst_caps_copy (caps); + + + return gst_pad_set_caps (pad, caps); +} + + static GstCaps * +src_getcaps (GstPad *pad) { - GstOmxBaseAudioDec *base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); - GstOmxAacDec *self = GST_OMX_AACDEC (omx_base); - - OMX_U32 streamFormat; - gint profile; - - GST_DEBUG_OBJECT (omx_base, "Begin Set-Up"); - - switch (self->aacversion) - { - case AAC_PROFILE_LC_SBR_PS: - profile = OMX_AUDIO_AACObjectHE_PS; - break; - case AAC_PROFILE_LC_SBR: - profile = OMX_AUDIO_AACObjectHE; - break; - case AAC_PROFILE_LC: - default: - profile = OMX_AUDIO_AACObjectLC; - break; - } - - // Does it come from a demuxer? - if(self->framed) - { - streamFormat = OMX_AUDIO_AACStreamFormatRAW; - GST_DEBUG_OBJECT (omx_base, "Format: Raw"); - } - else - { - streamFormat = OMX_AUDIO_AACStreamFormatMax; - GST_DEBUG_OBJECT (omx_base, "Format: Max"); - } - - { - OMX_AUDIO_PARAM_AACPROFILETYPE param; - G_OMX_PORT_GET_PARAM (omx_base->in_port, OMX_IndexParamAudioAac, ¶m); - param.eAACProfile = profile; - param.eAACStreamFormat = streamFormat; - G_OMX_PORT_SET_PARAM (omx_base->in_port, OMX_IndexParamAudioAac, ¶m); - } - - { - OMX_AUDIO_PARAM_PCMMODETYPE param; - G_OMX_PORT_GET_PARAM (omx_base->out_port, OMX_IndexParamAudioPcm, ¶m); - param.nSamplingRate = base_audiodec->rate; - GST_DEBUG_OBJECT (omx_base, "PCM Sample Rate: %ld", param.nSamplingRate); - G_OMX_PORT_SET_PARAM (omx_base->out_port, OMX_IndexParamAudioPcm, ¶m); - } + GstCaps *caps; + GstStructure *structure; + GstOmxBaseFilter *omx_base; + GstOmxBaseAudioDec *base_audiodec; + GstOmxAacDec* self; -#ifdef USE_OMXTIAUDIODEC - // This is specific for TI. - { - OMX_INDEXTYPE index; - TI_OMX_DSP_DEFINITION audioinfo; + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); + self = GST_OMX_AACDEC (omx_base); + { + /* set pcm port */ + OMX_AUDIO_PARAM_PCMMODETYPE param; - GOmxCore *gomx = omx_base->gomx; + } - memset (&audioinfo, 0, sizeof (audioinfo)); + return caps; +} + static GstCaps * +sink_getcaps (GstPad *pad) +{ + GstCaps *caps = NULL; + GstStructure *structure = NULL; + GstOmxBaseFilter *omx_base; + GstOmxBaseAudioDec *base_audiodec; + GstOmxAacDec* self; - audioinfo.framemode = self->framemode; - GST_DEBUG_OBJECT (omx_base, "Frame Mode: %d", audioinfo.framemode); - g_assert( - OMX_GetExtensionIndex ( - gomx->omx_handle, "OMX.TI.index.config.aacdecHeaderInfo", - &index) == OMX_ErrorNone); + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); + self = GST_OMX_AACDEC (omx_base); - g_assert( - OMX_SetConfig ( - gomx->omx_handle, index, - &audioinfo) == OMX_ErrorNone); - GST_DEBUG_OBJECT (omx_base, "End Set-Up"); - } -#endif + //OMX_AUDIO_PARAM_AACPROFILETYPE param; + + return caps; } -static void -type_instance_init (GTypeInstance *instance, - gpointer g_class) + static void +omx_setup (GstOmxBaseFilter *omx_base) { - GstOmxBaseFilter *omx_base; - GstOmxAacDec *self; + GstOmxBaseAudioDec *base_audiodec = GST_OMX_BASE_AUDIODEC (omx_base); + GstOmxAacDec *self = GST_OMX_AACDEC (omx_base); + //OMX_ERRORTYPE eError = OMX_ErrorUndefined; + OMX_PORT_PARAM_TYPE portInit; + OMX_PARAM_PORTDEFINITIONTYPE pInPortDef, pOutPortDef; + GOmxPort *port; + GOmxCore *gomx; + OMX_ERRORTYPE eError = OMX_ErrorNone; + + OMX_U32 streamFormat; + gint profile; + + gomx = (GOmxCore *) omx_base->gomx; + + GST_DEBUG_OBJECT (omx_base, "Begin Set-Up"); + + switch (self->aacversion) + { + case AAC_PROFILE_LC_SBR_PS: + profile = OMX_AUDIO_AACObjectHE_PS; + break; + case AAC_PROFILE_LC_SBR: + profile = OMX_AUDIO_AACObjectHE; + break; + case AAC_PROFILE_LC: + default: + profile = OMX_AUDIO_AACObjectLC; + break; + } + + // Does it come from a demuxer? + if(self->framed) + { + streamFormat = OMX_AUDIO_AACStreamFormatRAW; + GST_DEBUG_OBJECT (omx_base, "Format: Raw"); + } + else + { + streamFormat = OMX_AUDIO_AACStreamFormatMax; + GST_DEBUG_OBJECT (omx_base, "Format: Max"); + } + + { + OMX_AUDIO_PARAM_AACPROFILETYPE param; + G_OMX_PORT_GET_PARAM (omx_base->in_port, OMX_IndexParamAudioAac, ¶m); + param.eAACProfile = profile; + param.eAACStreamFormat = streamFormat; + G_OMX_PORT_SET_PARAM (omx_base->in_port, OMX_IndexParamAudioAac, ¶m); + } + + { + OMX_AUDIO_PARAM_PCMMODETYPE param; + G_OMX_PORT_GET_PARAM (omx_base->out_port, OMX_IndexParamAudioPcm, ¶m); + param.nSamplingRate = base_audiodec->rate; + GST_DEBUG_OBJECT (omx_base, "PCM Sample Rate: %ld", param.nSamplingRate); + G_OMX_PORT_SET_PARAM (omx_base->out_port, OMX_IndexParamAudioPcm, ¶m); + } + /*set port definition*/ +#if 1 + _G_OMX_INIT_PARAM(&portInit); + portInit.nPorts = 2; + portInit.nStartPortNumber = 0; + G_OMX_PORT_SET_PARAM(omx_base->in_port,OMX_IndexParamAudioInit,&portInit); + + _G_OMX_INIT_PARAM(&pInPortDef); + pInPortDef.nPortIndex = 0;//OMX_AUDDEC_INPUT_PORT; + pInPortDef.eDir = OMX_DirInput; + pInPortDef.nBufferCountActual = 1; + pInPortDef.nBufferCountMin = 1; + pInPortDef.nBufferSize = 4096; //width * height; + + pInPortDef.bEnabled = OMX_TRUE; + pInPortDef.bPopulated = OMX_FALSE; + pInPortDef.eDomain = OMX_PortDomainAudio; + pInPortDef.bBuffersContiguous = OMX_FALSE; + pInPortDef.nBufferAlignment = 32; + + /* OMX_VIDEO_PORTDEFINITION values for input port */ + pInPortDef.format.audio.cMIMEType = "ADEC"; + pInPortDef.format.audio.pNativeRender = NULL; + pInPortDef.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + pInPortDef.format.audio.bFlagErrorConcealment = OMX_FALSE; + G_OMX_PORT_SET_DEFINITION (omx_base->in_port, &pInPortDef); + + _G_OMX_INIT_PARAM(&pOutPortDef); + pOutPortDef.nPortIndex = 1; + pOutPortDef.eDir = OMX_DirOutput; + pOutPortDef.nBufferCountActual = 1; + pOutPortDef.nBufferCountMin = 1; + + /* for referance purpose, in PT mode, stride and height would be used by FQ + It is padded inside components */ + pOutPortDef.nBufferSize = 4608; + pOutPortDef.bEnabled = OMX_TRUE; + pOutPortDef.bPopulated = OMX_FALSE; + pOutPortDef.eDomain = OMX_PortDomainAudio; + pOutPortDef.bBuffersContiguous = OMX_FALSE; + pOutPortDef.nBufferAlignment = 32; + + /* OMX_VIDEO_PORTDEFINITION values for output port */ + pOutPortDef.format.audio.cMIMEType = "PCM"; + pOutPortDef.format.audio.pNativeRender = NULL; + pOutPortDef.format.audio.bFlagErrorConcealment = OMX_FALSE; + pOutPortDef.format.audio.eEncoding = OMX_AUDIO_CodingUnused; + G_OMX_PORT_SET_DEFINITION (omx_base->out_port, &pOutPortDef); +#endif + port = g_omx_core_get_port (gomx, "input", 0); + GST_DEBUG_OBJECT(self, "SendCommand(PortEnable, %x)", port->port_index); + eError = OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, port->port_index, NULL); + g_sem_down (port->core->port_sem); + if (eError != OMX_ErrorNone) { + printf("\nSend command for port enable on port index=%d failed returned eError=%x",eError); + } + + port = g_omx_core_get_port (gomx, "output", 1); + GST_DEBUG_OBJECT(self, "SendCommand(PortEnable, %x)", port->port_index); + eError = OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, 1, NULL); + g_sem_down (port->core->port_sem); + if (eError != OMX_ErrorNone) { + printf("\nSend command for port enable on port index=%d failed returned eError=%x",port->port_index,eError); + } + +#ifdef USE_OMXTIAUDIODEC + // This is specific for TI. + { + OMX_INDEXTYPE index; + TI_OMX_DSP_DEFINITION audioinfo; - self = GST_OMX_AACDEC (instance); - omx_base = GST_OMX_BASE_FILTER (instance); - GST_DEBUG_OBJECT (omx_base, "start"); + GOmxCore *gomx = omx_base->gomx; - omx_base->omx_setup = omx_setup; + memset (&audioinfo, 0, sizeof (audioinfo)); - gst_pad_set_setcaps_function (omx_base->sinkpad, sink_setcaps); + audioinfo.framemode = self->framemode; + GST_DEBUG_OBJECT (omx_base, "Frame Mode: %d", audioinfo.framemode); - g_object_set (instance, - "input-buffers", 3, - "output-buffers", 3, - NULL); + g_assert( + OMX_GetExtensionIndex ( + gomx->omx_handle, "OMX.TI.index.config.aacdecHeaderInfo", + &index) == OMX_ErrorNone); + + g_assert( + OMX_SetConfig ( + gomx->omx_handle, index, + &audioinfo) == OMX_ErrorNone); + + GST_DEBUG_OBJECT (omx_base, "End Set-Up"); + } +#endif } + + static void +type_instance_init (GTypeInstance *instance, + gpointer g_class) +{ + GstOmxBaseFilter *omx_base; + GstOmxAacDec *self; + + self = GST_OMX_AACDEC (instance); + omx_base = GST_OMX_BASE_FILTER (instance); + //GST_DEBUG_OBJECT (omx_base, "start"); + omx_base->omx_setup = omx_setup; + //omx_base->in_port->always_copy = FALSE; + omx_base->out_port->always_copy = TRUE; + + gst_pad_set_setcaps_function (omx_base->sinkpad, sink_setcaps); + gst_pad_set_getcaps_function (omx_base->srcpad, src_getcaps); + gst_pad_set_getcaps_function (omx_base->sinkpad, sink_getcaps); + gst_pad_set_setcaps_function (omx_base->srcpad, src_setcaps); +} + + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.c index 7be7249..a725b0d 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.c @@ -33,7 +33,7 @@ enum ARG_OUTPUT_FORMAT, }; -#define DEFAULT_BITRATE 64000 /* Guarantee that all the 3 formats will work using this default. */ +#define DEFAULT_BITRATE 128000 /* Guarantee that all the 3 formats will work using this default. */ #define MAX_BITRATE 256000 /* Maximum value supported by the component */ #define DEFAULT_PROFILE OMX_AUDIO_AACObjectLC #define DEFAULT_OUTPUT_FORMAT OMX_AUDIO_AACStreamFormatRAW @@ -41,10 +41,20 @@ enum #define DEFAULT_CHANNELS 2 #define IN_BUFFER_SIZE 1024*8 /* 1024*8 Recommended buffer size */ #define OUT_BUFFER_SIZE 1024*8 /* 1024*8 Recommended buffer size */ +#define OMX_AUDENC_INPUT_PORT 0 +#define OMX_AUDENC_OUTPUT_PORT 1 +#define NUM_OF_IN_BUFFERS 1 +#define NUM_OF_OUT_BUFFERS 1 +#define NUM_OF_PORTS 2 +#define START_PORT_NUM 0 GSTOMX_BOILERPLATE (GstOmxAacEnc, gst_omx_aacenc, GstOmxBaseFilter, GST_OMX_BASE_FILTER_TYPE); #define GST_TYPE_OMX_AACENC_PROFILE (gst_omx_aacenc_profile_get_type ()) + +gint rateIdx[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000, + 11025,8000,7350}; + static GType gst_omx_aacenc_profile_get_type (void) { @@ -99,6 +109,48 @@ gst_omx_aacenc_output_format_get_type (void) return gst_omx_aacenc_output_format_type; } +static void +settings_changed_cb (GOmxCore *core) +{ + + GstOmxBaseFilter *omx_base; + guint rate; + guint channels; + guint profile; + + omx_base = core->object; + GST_DEBUG_OBJECT (omx_base, "settings changed"); + + { + OMX_AUDIO_PARAM_AACPROFILETYPE param; + _G_OMX_INIT_PARAM(¶m); + G_OMX_PORT_GET_PARAM (omx_base->out_port, OMX_IndexParamAudioAac, ¶m); + rate = param.nSampleRate; + channels = param.nChannels; + profile = param.eAACProfile; + + if (rate == 0) + { + /** @todo: this shouldn't happen. */ + GST_WARNING_OBJECT (omx_base, "Bad samplerate"); + rate = DEFAULT_RATE; + channels = DEFAULT_CHANNELS; + } + } + + { + GstCaps *new_caps = NULL; + new_caps = gst_caps_new_simple ("audio/mpeg", + "mpegversion", G_TYPE_INT, profile, + "rate", G_TYPE_INT, rate, + "channels", G_TYPE_INT, channels, + NULL); + + GST_INFO_OBJECT (omx_base, "caps are: %" GST_PTR_FORMAT, new_caps); + gst_pad_set_caps (omx_base->srcpad, new_caps); + } + +} static GstCaps * generate_src_template (void) @@ -307,49 +359,280 @@ sink_setcaps (GstPad *pad, gst_structure_get_int (structure, "rate", &self->rate); gst_structure_get_int (structure, "channels", &self->channels); + + { + /* set pcm port */ + OMX_AUDIO_PARAM_PCMMODETYPE param; + G_OMX_PORT_GET_PARAM (omx_base->in_port, OMX_IndexParamAudioPcm, ¶m); + + param.nSamplingRate = self->rate; + param.nChannels = self->channels; + + G_OMX_PORT_SET_PARAM(omx_base->in_port, OMX_IndexParamAudioPcm, ¶m); + + } + self->inport_configured = TRUE; + { - GstCaps *src_caps; + GstCaps *sink_caps; - src_caps = gst_caps_new_simple ("audio/mpeg", + sink_caps = gst_caps_new_simple ("audio/x-raw-int", "mpegversion", G_TYPE_INT, 4, "rate", G_TYPE_INT, self->rate, "channels", G_TYPE_INT, self->channels, NULL); - GST_INFO_OBJECT (omx_base, "src caps are: %" GST_PTR_FORMAT, src_caps); + GST_INFO_OBJECT (omx_base, "src caps are: %" GST_PTR_FORMAT, sink_caps); + + + omx_base->in_port->caps = gst_caps_copy (sink_caps); + + gst_caps_unref (sink_caps); + } + + return gst_pad_set_caps (pad, caps); +} + +static GstCaps * +sink_getcaps (GstPad *pad) +{ + + GstCaps *caps = NULL; + GstStructure *structure = NULL; + GstOmxBaseFilter *omx_base; + + GstOmxAacEnc* self; + + + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + + self = GST_OMX_AACENC (omx_base); + if (omx_base->gomx->omx_state > OMX_StateLoaded) + { + /* currently, we cannot change caps once out of loaded.. later this + * could possibly be supported by enabling/disabling the port.. + */ + GST_DEBUG_OBJECT (self, "cannot getcaps in %d state", omx_base->gomx->omx_state); + return GST_PAD_CAPS (pad); + } + if (self->inport_configured) + { + OMX_AUDIO_PARAM_PCMMODETYPE param; + + G_OMX_PORT_GET_PARAM (omx_base->in_port, OMX_IndexParamAudioPcm, ¶m); + caps = gst_caps_new_empty (); + + GstStructure *struc = ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "rate", G_TYPE_INT, param.nSamplingRate, + "signed", G_TYPE_BOOLEAN, TRUE, + "channels", G_TYPE_INT, param.nChannels, + NULL); + gst_caps_append_structure (caps, structure); + } + else + { + GstPadTemplate *template; + template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, + generate_sink_template ()); + /* we don't have valid width/height/etc yet, so just use the template.. */ + caps = gst_pad_template_get_caps(template); + + GST_DEBUG_OBJECT (self, "caps=%"GST_PTR_FORMAT, caps); + } + + return caps; + +} + +static guint gst_get_aac_rateIdx (guint rate) +{ + gint i; + + for (i=0; i < 13; i++){ + if (rate >= rateIdx[i]) + return i; + } + + return 15; +} + +static GstBuffer *gst_omx_aacenc_generate_codec_data (GstOmxBaseFilter *omx_base){ + GstBuffer *codec_data = NULL; + guchar *data; + guint sr_idx; + GstOmxAacEnc *self; + + self = GST_OMX_AACENC (omx_base); + /* + * Now create the codec data header, it goes like + * 5 bit: profile + * 4 bit: sample rate index + * 4 bit: number of channels + * 3 bit: unused + */ + sr_idx = gst_get_aac_rateIdx(self->rate); + codec_data = gst_buffer_new_and_alloc(2); + data = GST_BUFFER_DATA(codec_data); + data[0] = ((self->profile & 0x1F) << 3) | ((sr_idx & 0xE) >> 1); + data[1] = ((sr_idx & 0x1) << 7) | ((self->channels & 0xF) << 3); + + return codec_data; +} - gst_pad_set_caps (omx_base->srcpad, src_caps); +static gboolean +src_setcaps (GstPad *pad, + GstCaps *caps) +{ + + GstStructure *structure; + GstOmxBaseFilter *omx_base; + + GstOmxAacEnc* self; + + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + + self = GST_OMX_AACENC (omx_base); + + GST_INFO_OBJECT (omx_base, "setcaps (sink): %" GST_PTR_FORMAT, caps); + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (structure, "rate", &self->rate); + gst_structure_get_int (structure, "channels", &self->channels); + gst_structure_get_int (structure, "mpegversion", &self->profile); + + { + /* set aac profile type port */ + OMX_AUDIO_PARAM_AACPROFILETYPE param; + + G_OMX_PORT_GET_PARAM (omx_base->out_port, OMX_IndexParamAudioAac, ¶m); + + param.nSampleRate = self->rate; + param.nChannels = self->channels; + param.eAACProfile = self->profile; + + G_OMX_PORT_SET_PARAM(omx_base->out_port, OMX_IndexParamAudioAac, ¶m); + + } - gst_caps_unref (src_caps); + if(self->output_format == OMX_AUDIO_AACStreamFormatADIF) + { + GstBuffer *codec_data; + codec_data = gst_omx_aacenc_generate_codec_data(omx_base); + gst_caps_set_simple (caps, "codec_data", + GST_TYPE_BUFFER, codec_data, (char *)NULL); + gst_buffer_unref (codec_data); } + omx_base->in_port->caps = gst_caps_copy (caps); + + return gst_pad_set_caps (pad, caps); + +} + +static GstCaps * +src_getcaps (GstPad *pad) +{ + + GstCaps *caps = NULL; + GstStructure *structure = NULL; + GstOmxBaseFilter *omx_base; + GstOmxAacEnc* self; + + + omx_base = GST_OMX_BASE_FILTER (GST_PAD_PARENT (pad)); + self = GST_OMX_AACENC (omx_base); + + if (omx_base->gomx->omx_state > OMX_StateLoaded) + { + /* currently, we cannot change caps once out of loaded.. later this + * could possibly be supported by enabling/disabling the port.. + */ + GST_DEBUG_OBJECT (self, "cannot getcaps in %d state", omx_base->gomx->omx_state); + return GST_PAD_CAPS (pad); + } + if (self->inport_configured) + { + + OMX_AUDIO_PARAM_AACPROFILETYPE param; + G_OMX_PORT_GET_PARAM (omx_base->out_port, OMX_IndexParamAudioAac, ¶m); + caps = gst_caps_new_empty (); + + GstStructure *struc = gst_structure_new ("audio/mpeg", + "mpegversion", G_TYPE_INT, &self->profile, + "rate", G_TYPE_INT,self->rate, + "channels", G_TYPE_INT, self->channels, + NULL); + gst_caps_append_structure (caps, struc); + } + else + { + GstPadTemplate *template; + template = gst_pad_template_new ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, + generate_src_template ()); + /* we don't have valid width/height/etc yet, so just use the template.. */ + caps = gst_pad_template_get_caps(template); + + GST_DEBUG_OBJECT (self, "caps=%"GST_PTR_FORMAT, caps); + } + + + + return caps; + } static void omx_setup (GstOmxBaseFilter *omx_base) { + GstOmxAacEnc *self; GOmxCore *gomx; + GOmxPort *port; + + OMX_PORT_PARAM_TYPE portInit; + OMX_PARAM_PORTDEFINITIONTYPE pInPortDef, pOutPortDef; + OMX_ERRORTYPE eError = OMX_ErrorNone; self = GST_OMX_AACENC (omx_base); gomx = (GOmxCore *) omx_base->gomx; - + + + GST_INFO_OBJECT (omx_base, "begin"); - /* Input port configuration. */ + _G_OMX_INIT_PARAM(&portInit); + portInit.nPorts = NUM_OF_PORTS; + portInit.nStartPortNumber = START_PORT_NUM; + G_OMX_PORT_SET_PARAM(omx_base->in_port,OMX_IndexParamAudioInit,&portInit); - { - OMX_PARAM_PORTDEFINITIONTYPE param; - G_OMX_PORT_GET_DEFINITION (omx_base->in_port, ¶m); + _G_OMX_INIT_PARAM(&pInPortDef); + pInPortDef.nPortIndex = OMX_AUDENC_INPUT_PORT; + G_OMX_PORT_GET_DEFINITION (omx_base->in_port, &pInPortDef); + pInPortDef.nBufferCountActual = NUM_OF_IN_BUFFERS; + pInPortDef.format.audio.eEncoding = OMX_AUDIO_CodingPCM; + G_OMX_PORT_SET_DEFINITION (omx_base->in_port, &pInPortDef); - param.nBufferSize = IN_BUFFER_SIZE; - G_OMX_PORT_SET_DEFINITION (omx_base->in_port, ¶m); - } + _G_OMX_INIT_PARAM(&pOutPortDef); + pOutPortDef.nPortIndex = OMX_AUDENC_OUTPUT_PORT; + G_OMX_PORT_GET_DEFINITION (omx_base->out_port, &pOutPortDef); + pOutPortDef.nBufferCountActual = NUM_OF_OUT_BUFFERS; + pOutPortDef.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + G_OMX_PORT_SET_DEFINITION (omx_base->out_port, &pOutPortDef); + + + + /* PCM configuration. */ { OMX_AUDIO_PARAM_PCMMODETYPE param; - + _G_OMX_INIT_PARAM(¶m); G_OMX_PORT_GET_PARAM (omx_base->in_port, OMX_IndexParamAudioPcm, ¶m); param.nSamplingRate = self->rate; @@ -358,18 +641,10 @@ omx_setup (GstOmxBaseFilter *omx_base) G_OMX_PORT_SET_PARAM (omx_base->in_port, OMX_IndexParamAudioPcm, ¶m); } - /* output port configuration. */ - { - OMX_PARAM_PORTDEFINITIONTYPE param; - G_OMX_PORT_GET_DEFINITION (omx_base->out_port, ¶m); - - param.nBufferSize = OUT_BUFFER_SIZE; - G_OMX_PORT_SET_DEFINITION (omx_base->out_port, ¶m); - } /* AAC configuration. */ { OMX_AUDIO_PARAM_AACPROFILETYPE param; - + _G_OMX_INIT_PARAM(¶m); G_OMX_PORT_GET_PARAM (omx_base->out_port, OMX_IndexParamAudioAac, ¶m); param.nSampleRate = self->rate; @@ -387,6 +662,38 @@ omx_setup (GstOmxBaseFilter *omx_base) G_OMX_PORT_SET_PARAM (omx_base->out_port, OMX_IndexParamAudioAac, ¶m); } + GST_DEBUG_OBJECT(self, "SendCommand(PortEnable, %x)", port->port_index); + port = g_omx_core_get_port (gomx, "input", 0); + eError = OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, port->port_index, NULL); + g_sem_down (port->core->port_sem); + + if (eError != OMX_ErrorNone) + { + + GST_DEBUG_OBJECT(self, "port enable on port %d failed error=%x", port->port_index,eError); + } + else + { + GST_DEBUG_OBJECT(self, "port enabled on port index %d ", port->port_index ); + } + + port = g_omx_core_get_port (gomx, "output", 1); + GST_DEBUG_OBJECT(self, "SendCommand(PortEnable, %x)", port->port_index); + eError = OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, 1, NULL); + g_sem_down (port->core->port_sem); + + if (eError != OMX_ErrorNone) + { + GST_DEBUG_OBJECT(self, "port enable on port %d failed error=%x", port->port_index,eError); + } + else + { + GST_DEBUG_OBJECT(self, "port enabled on port index %d ", port->port_index ); + } + + GST_INFO_OBJECT (omx_base, "end"); } @@ -401,8 +708,13 @@ type_instance_init (GTypeInstance *instance, self = GST_OMX_AACENC (instance); omx_base->omx_setup = omx_setup; + omx_base->gomx->settings_changed_cb = settings_changed_cb; + omx_base->out_port->always_copy = TRUE; gst_pad_set_setcaps_function (omx_base->sinkpad, sink_setcaps); + gst_pad_set_getcaps_function (omx_base->sinkpad, sink_getcaps); + gst_pad_set_setcaps_function (omx_base->srcpad, src_setcaps); + gst_pad_set_getcaps_function (omx_base->srcpad, src_getcaps); self->bitrate = DEFAULT_BITRATE; self->profile = DEFAULT_PROFILE; diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.h index 7a6ff0d..9db435d 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_aacenc.h @@ -42,6 +42,7 @@ struct GstOmxAacEnc gint output_format; gint rate; gint channels; + gboolean inport_configured; }; struct GstOmxAacEncClass diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_audiodec.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_audiodec.c index d6a3a86..649c7a9 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_audiodec.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_audiodec.c @@ -95,6 +95,7 @@ settings_changed_cb (GOmxCore *core) /** @todo: this shouldn't happen. */ GST_WARNING_OBJECT (omx_base, "Bad samplerate"); rate = 44100; + channels = 2; } } diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_ctrl.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_ctrl.h index bcf23dc..4e70801 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_ctrl.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_ctrl.h @@ -25,7 +25,6 @@ #include <gst/gst.h> #include <gst/base/gstbasetransform.h> -#include <xdc/std.h> #include <OMX_TI_Index.h> #include <OMX_TI_Common.h> #include <omx_vfdc.h> diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.c index 87770b5..a2de97d 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.c @@ -3,6 +3,9 @@ * * Author: Felipe Contreras <felipe.contreras@nokia.com> * + * Modified by: David Soto <david.soto@ridgerun.com> + * Copyright (C) 2011 RidgeRun + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation @@ -101,32 +104,34 @@ setup_input_buffer (GstOmxBaseFilter *self, GstBuffer *buf) /* retrieve incoming buffer port information */ port = GST_GET_OMXPORT (buf); - /* configure input buffer size to match with upstream buffer */ - G_OMX_PORT_GET_DEFINITION (self->in_port, ¶m); - param.nBufferSize = GST_BUFFER_SIZE (buf); - param.nBufferCountActual = port->num_buffers; - G_OMX_PORT_SET_DEFINITION (self->in_port, ¶m); - - /* allocate resource to save the incoming buffer port pBuffer pointer in - * OmxBufferInfo structure. - */ - in_port = self->in_port; - in_port->share_buffer_info = malloc (sizeof(OmxBufferInfo)); - in_port->share_buffer_info->pBuffer = malloc (sizeof(int) * port->num_buffers); - for (i=0; i < port->num_buffers; i++) { - in_port->share_buffer_info->pBuffer[i] = port->buffers[i]->pBuffer; - } - - /* disable omx_allocate alloc flag, so that we can fall back to shared method */ - self->in_port->omx_allocate = FALSE; - self->in_port->always_copy = FALSE; - } - else - { - /* ask openmax to allocate input buffer */ - self->in_port->omx_allocate = TRUE; - self->in_port->always_copy = TRUE; - } + /* Check if output port has set always_copy */ + if (port->always_copy != TRUE) { + /* configure input buffer size to match with upstream buffer */ + G_OMX_PORT_GET_DEFINITION (self->in_port, ¶m); + param.nBufferSize = GST_BUFFER_SIZE (buf); + param.nBufferCountActual = port->num_buffers; + G_OMX_PORT_SET_DEFINITION (self->in_port, ¶m); + + /* allocate resource to save the incoming buffer port pBuffer pointer in + * OmxBufferInfo structure. + */ + in_port = self->in_port; + in_port->share_buffer_info = malloc (sizeof(OmxBufferInfo)); + in_port->share_buffer_info->pBuffer = malloc (sizeof(int) * port->num_buffers); + for (i=0; i < port->num_buffers; i++) { + in_port->share_buffer_info->pBuffer[i] = port->buffers[i]->pBuffer; + } + + /* disable omx_allocate alloc flag, so that we can fall back to shared method */ + self->in_port->omx_allocate = FALSE; + self->in_port->always_copy = FALSE; + + return; + } + } + /* ask openmax to allocate input buffer */ + self->in_port->omx_allocate = TRUE; + self->in_port->always_copy = TRUE; } static GstStateChangeReturn @@ -408,6 +413,8 @@ push_buffer (GstOmxBaseFilter *self, } PRINT_BUFFER (self, buf); + if (self->push_cb) + self->push_cb (self, buf); /** @todo check if tainted */ GST_LOG_OBJECT (self, "begin"); diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.h index be5b4e7..1280aa4 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter.h @@ -34,6 +34,7 @@ G_BEGIN_DECLS typedef struct GstOmxBaseFilter GstOmxBaseFilter; typedef struct GstOmxBaseFilterClass GstOmxBaseFilterClass; typedef void (*GstOmxBaseFilterCb) (GstOmxBaseFilter *self); +typedef void (*GstOmxBaseFilterPushCb) (GstOmxBaseFilter *self, GstBuffer *buf); #include "gstomx_util.h" #include <async_queue.h> @@ -56,6 +57,7 @@ struct GstOmxBaseFilter GMutex *ready_lock; GstOmxBaseFilterCb omx_setup; + GstOmxBaseFilterPushCb push_cb; GstFlowReturn last_pad_push_return; GstBuffer *codec_data; GstClockTime duration; diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter2.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter2.c new file mode 100644 index 0000000..fa40c95 --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter2.c @@ -0,0 +1,1028 @@ +/* + * Copyright (C) 2007-2009 Nokia Corporation. + * + * Author: Felipe Contreras <felipe.contreras@nokia.com> + * + * Modified by: David Soto <david.soto@ridgerun.com> + * Copyright (C) 2011 RidgeRun + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "gstomx_base_filter2.h" +#include "gstomx.h" +#include "gstomx_interface.h" +#include "gstomx_buffertransport.h" + +enum +{ + ARG_0, + ARG_COMPONENT_ROLE, + ARG_COMPONENT_NAME, + ARG_LIBRARY_NAME, + ARG_USE_TIMESTAMPS, + ARG_NUM_INPUT_BUFFERS, + ARG_NUM_OUTPUT_BUFFERS, + ARG_GEN_TIMESTAMPS +}; + +static void init_interfaces (GType type); +GSTOMX_BOILERPLATE_FULL (GstOmxBaseFilter2, gst_omx_base_filter2, GstElement, GST_TYPE_ELEMENT, init_interfaces); + + +static GstFlowReturn push_buffer (GstOmxBaseFilter2 *self, GstBuffer *buf); +static GstFlowReturn pad_chain (GstPad *pad, GstBuffer *buf); +static gboolean pad_event (GstPad *pad, GstEvent *event); + + +static void +setup_ports (GstOmxBaseFilter2 *self) +{ + OMX_PARAM_PORTDEFINITIONTYPE param; + int i; + gboolean omx_allocate, share_buffer; + gboolean set_omx_allocate = FALSE, set_share_buffer = FALSE; + + if (g_getenv ("OMX_ALLOCATE_ON")) + { + GST_DEBUG_OBJECT (self, "OMX_ALLOCATE_ON"); + omx_allocate = TRUE; + share_buffer = FALSE; + set_omx_allocate = set_share_buffer = TRUE; + } + else if (g_getenv ("OMX_SHARE_HACK_ON")) + { + GST_DEBUG_OBJECT (self, "OMX_SHARE_HACK_ON"); + share_buffer = TRUE; + set_share_buffer = TRUE; + } + else if (g_getenv ("OMX_SHARE_HACK_OFF")) + { + GST_DEBUG_OBJECT (self, "OMX_SHARE_HACK_OFF"); + share_buffer = FALSE; + set_share_buffer = TRUE; + } + + /* Input port configuration. */ + G_OMX_PORT_GET_DEFINITION (self->in_port, ¶m); + g_omx_port_setup (self->in_port, ¶m); + gst_pad_set_element_private (self->sinkpad, self->in_port); + if (set_omx_allocate) self->in_port->omx_allocate = omx_allocate; + if (set_share_buffer) self->in_port->share_buffer = share_buffer; + + /* Output port configuration. */ + for (i = 0; i < NUM_OUTPUTS; i++) { + G_OMX_PORT_GET_DEFINITION (self->out_port[i], ¶m); + g_omx_port_setup (self->out_port[i], ¶m); + gst_pad_set_element_private (self->srcpad[i], self->out_port[i]); + if (set_omx_allocate) self->out_port[i]->omx_allocate = omx_allocate; + if (set_share_buffer) self->out_port[i]->share_buffer = share_buffer; + } +} + +static void +setup_input_buffer (GstOmxBaseFilter2 *self, GstBuffer *buf) +{ + if (GST_IS_OMXBUFFERTRANSPORT (buf)) + { + OMX_PARAM_PORTDEFINITIONTYPE param, peer_param; + GOmxPort *port, *in_port; + gint i, shift = 0; + + /* retrieve incoming buffer port information */ + port = GST_GET_OMXPORT (buf); + + /* configure input buffer size to match with upstream buffer */ + G_OMX_PORT_GET_DEFINITION (self->in_port, ¶m); + G_OMX_PORT_GET_DEFINITION (port, &peer_param); + + printf("this input params: %dx%d,%d %d %d\n", param.format.video.nFrameWidth, + param.format.video.nFrameHeight, + param.format.video.nStride, + param.nBufferSize, param.nBufferCountActual); + printf("peer output params: %dx%d,%d %d %d\n", peer_param.format.video.nFrameWidth, + peer_param.format.video.nFrameHeight, + peer_param.format.video.nStride, + peer_param.nBufferSize, peer_param.nBufferCountActual); + printf("incoming buffer: nFilledLen: %d, nOffset: %d nFlags: %x\n", + GST_GET_OMXBUFFER(buf)->nFilledLen, + GST_GET_OMXBUFFER(buf)->nOffset, + GST_GET_OMXBUFFER(buf)->nFlags); + + param.nBufferSize = GST_BUFFER_SIZE (buf); + if (self->input_fields_separately) param.nBufferCountActual = port->num_buffers * 2; + else param.nBufferCountActual = port->num_buffers; + G_OMX_PORT_SET_DEFINITION (self->in_port, ¶m); + + /* allocate resource to save the incoming buffer port pBuffer pointer in + * OmxBufferInfo structure. + */ + in_port = self->in_port; + in_port->share_buffer_info = malloc (sizeof(OmxBufferInfo)); + if (self->input_fields_separately) { + int t1, t2; + t1 = GST_GET_OMXBUFFER(buf)->nOffset / param.format.video.nStride; + t2 = t1 + t1 + ((param.format.video.nFrameHeight + 7) & 0xFFFFFFF8); + t1 = t2 * param.format.video.nStride; + self->second_field_offset = ( GST_GET_OMXBUFFER(buf)->nFilledLen + GST_GET_OMXBUFFER(buf)->nOffset ) / 3; + if (self->second_field_offset != t1) { + printf("Second field offset does not look right... correcting it from %d to %d\n", + self->second_field_offset, t1); + self->second_field_offset = t1; + } + in_port->share_buffer_info->pBuffer = malloc (sizeof(int) * port->num_buffers * 2); + for (i=0; i < port->num_buffers; i++) { + in_port->share_buffer_info->pBuffer[i<<1] = port->buffers[i]->pBuffer; + in_port->share_buffer_info->pBuffer[(i<<1)+1] = port->buffers[i]->pBuffer + + self->second_field_offset; + } + } else { + in_port->share_buffer_info->pBuffer = malloc (sizeof(int) * port->num_buffers); + for (i=0; i < port->num_buffers; i++) { + in_port->share_buffer_info->pBuffer[i] = port->buffers[i]->pBuffer; + } + } + + /* disable omx_allocate alloc flag, so that we can fall back to shared method */ + self->in_port->omx_allocate = FALSE; + self->in_port->always_copy = FALSE; + } + else + { + /* ask openmax to allocate input buffer */ + self->in_port->omx_allocate = TRUE; + self->in_port->always_copy = TRUE; + self->input_fields_separately = FALSE; + } +} + +static GstStateChangeReturn +change_state (GstElement *element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstOmxBaseFilter2 *self; + GOmxCore *core; + int i; + + self = GST_OMX_BASE_FILTER2 (element); + core = self->gomx; + + GST_INFO_OBJECT (self, "begin: changing state %s -> %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); + + switch (transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + g_omx_core_init (core); + if (core->omx_state != OMX_StateLoaded) + { + ret = GST_STATE_CHANGE_FAILURE; + goto leave; + } + break; + + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + if (ret == GST_STATE_CHANGE_FAILURE) + goto leave; + + switch (transition) + { + case GST_STATE_CHANGE_PAUSED_TO_READY: + g_mutex_lock (self->ready_lock); + if (self->ready) + { + /* unlock */ + g_omx_port_finish (self->in_port); + for (i = 0; i < NUM_OUTPUTS; i++) + g_omx_port_finish (self->out_port[i]); + + g_omx_core_stop (core); + g_omx_core_unload (core); + self->ready = FALSE; + } + g_mutex_unlock (self->ready_lock); + if (core->omx_state != OMX_StateLoaded && + core->omx_state != OMX_StateInvalid) + { + ret = GST_STATE_CHANGE_FAILURE; + goto leave; + } + break; + + case GST_STATE_CHANGE_READY_TO_NULL: + g_omx_core_deinit (core); + break; + + default: + break; + } + +leave: + GST_LOG_OBJECT (self, "end"); + + return ret; +} + +static void +finalize (GObject *obj) +{ + GstOmxBaseFilter2 *self; + + self = GST_OMX_BASE_FILTER2 (obj); + + if (self->codec_data) + { + gst_buffer_unref (self->codec_data); + self->codec_data = NULL; + } + + g_omx_core_free (self->gomx); + + g_free (self->omx_role); + g_free (self->omx_component); + g_free (self->omx_library); + + g_mutex_free (self->ready_lock); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +set_property (GObject *obj, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GstOmxBaseFilter2 *self; + + self = GST_OMX_BASE_FILTER2 (obj); + + switch (prop_id) + { + case ARG_COMPONENT_ROLE: + g_free (self->omx_role); + self->omx_role = g_value_dup_string (value); + break; + case ARG_COMPONENT_NAME: + g_free (self->omx_component); + self->omx_component = g_value_dup_string (value); + break; + case ARG_LIBRARY_NAME: + g_free (self->omx_library); + self->omx_library = g_value_dup_string (value); + break; + case ARG_USE_TIMESTAMPS: + self->gomx->use_timestamps = g_value_get_boolean (value); + break; + case ARG_GEN_TIMESTAMPS: + self->gomx->gen_timestamps = g_value_get_boolean (value); + break; + case ARG_NUM_INPUT_BUFFERS: + { + OMX_PARAM_PORTDEFINITIONTYPE param; + OMX_U32 nBufferCountActual = g_value_get_uint (value); + G_OMX_PORT_GET_DEFINITION (self->in_port, ¶m); + g_return_if_fail (nBufferCountActual >= param.nBufferCountMin); + param.nBufferCountActual = nBufferCountActual; + G_OMX_PORT_SET_DEFINITION (self->in_port, ¶m); + } + break; + case ARG_NUM_OUTPUT_BUFFERS: + { + OMX_PARAM_PORTDEFINITIONTYPE param; + OMX_U32 nBufferCountActual = g_value_get_uint (value); + int i; + for (i = 0; i < NUM_OUTPUTS; i++) { + G_OMX_PORT_GET_DEFINITION (self->out_port[i], ¶m); + g_return_if_fail (nBufferCountActual >= param.nBufferCountMin); + param.nBufferCountActual = nBufferCountActual; + G_OMX_PORT_SET_DEFINITION (self->out_port[i], ¶m); + } + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *obj, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GstOmxBaseFilter2 *self; + + self = GST_OMX_BASE_FILTER2 (obj); + + switch (prop_id) + { + case ARG_COMPONENT_ROLE: + g_value_set_string (value, self->omx_role); + break; + case ARG_COMPONENT_NAME: + g_value_set_string (value, self->omx_component); + break; + case ARG_LIBRARY_NAME: + g_value_set_string (value, self->omx_library); + break; + case ARG_USE_TIMESTAMPS: + g_value_set_boolean (value, self->gomx->use_timestamps); + break; + case ARG_GEN_TIMESTAMPS: + g_value_set_boolean (value, self->gomx->gen_timestamps); + break; + case ARG_NUM_INPUT_BUFFERS: + case ARG_NUM_OUTPUT_BUFFERS: + { + OMX_PARAM_PORTDEFINITIONTYPE param; + GOmxPort *port = (prop_id == ARG_NUM_INPUT_BUFFERS) ? + self->in_port : self->out_port[0]; + + G_OMX_PORT_GET_DEFINITION (port, ¶m); + + g_value_set_uint (value, param.nBufferCountActual); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + +static void +type_base_init (gpointer g_class) +{ +} + +static void +type_class_init (gpointer g_class, + gpointer class_data) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstOmxBaseFilter2Class *bclass; + + gobject_class = G_OBJECT_CLASS (g_class); + gstelement_class = GST_ELEMENT_CLASS (g_class); + bclass = GST_OMX_BASE_FILTER2_CLASS (g_class); + + gobject_class->finalize = finalize; + gstelement_class->change_state = change_state; + bclass->push_buffer = push_buffer; + bclass->pad_chain = pad_chain; + bclass->pad_event = pad_event; + + /* Properties stuff */ + { + gobject_class->set_property = set_property; + gobject_class->get_property = get_property; + + g_object_class_install_property (gobject_class, ARG_COMPONENT_ROLE, + g_param_spec_string ("component-role", "Component role", + "Role of the OpenMAX IL component", + NULL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_COMPONENT_NAME, + g_param_spec_string ("component-name", "Component name", + "Name of the OpenMAX IL component to use", + NULL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_LIBRARY_NAME, + g_param_spec_string ("library-name", "Library name", + "Name of the OpenMAX IL implementation library to use", + NULL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_USE_TIMESTAMPS, + g_param_spec_boolean ("use-timestamps", "Use timestamps", + "Whether or not to use timestamps", + TRUE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_GEN_TIMESTAMPS, + g_param_spec_boolean ("gen-timestamps", "Generate timestamps", + "Whether or not to generate timestamps using interpolation/extrapolation", + TRUE, G_PARAM_READWRITE)); + + /* note: the default values for these are just a guess.. since we wouldn't know + * until the OMX component is constructed. But that is ok, these properties are + * only for debugging + */ + g_object_class_install_property (gobject_class, ARG_NUM_INPUT_BUFFERS, + g_param_spec_uint ("input-buffers", "Input buffers", + "The number of OMX input buffers", + 1, 10, 4, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_NUM_OUTPUT_BUFFERS, + g_param_spec_uint ("output-buffers", "Output buffers", + "The number of OMX output buffers", + 1, 10, 4, G_PARAM_READWRITE)); + } +} + +static GstFlowReturn +push_buffer (GstOmxBaseFilter2 *self, + GstBuffer *buf) +{ + GstFlowReturn ret = GST_FLOW_ERROR; + int i; + + for (i = 0; i< NUM_OUTPUTS; i++) { + if (GST_GET_OMXPORT(buf) == self->out_port[i]) { + break; + } + } + + if (i == NUM_OUTPUTS) return ret; + + GST_BUFFER_DURATION (buf) = self->duration; + + if (self->gomx->gen_timestamps == TRUE) { + if (GST_CLOCK_TIME_NONE == GST_BUFFER_TIMESTAMP(buf) && + GST_CLOCK_TIME_NONE != self->last_buf_timestamp[i] && + GST_CLOCK_TIME_NONE != self->duration) { + GST_BUFFER_TIMESTAMP(buf) = self->last_buf_timestamp[i] + self->duration; + } + self->last_buf_timestamp[i] = GST_BUFFER_TIMESTAMP(buf); + } + + PRINT_BUFFER (self, buf); + if (self->push_cb) + self->push_cb (self, buf); + + /** @todo check if tainted */ + GST_LOG_OBJECT (self, "begin"); + ret = gst_pad_push (self->srcpad[i], buf); + GST_LOG_OBJECT (self, "end"); + + return ret; +} + +static void +output_loop (gpointer data) +{ + GstPad *pad; + GOmxCore *gomx; + GOmxPort *out_port; + GstOmxBaseFilter2 *self; + GstFlowReturn ret = GST_FLOW_OK; + GstOmxBaseFilter2Class *bclass; + + pad = data; + self = GST_OMX_BASE_FILTER2 (gst_pad_get_parent (pad)); + gomx = self->gomx; + + bclass = GST_OMX_BASE_FILTER2_GET_CLASS (self); + + GST_LOG_OBJECT (self, "begin"); + + if (!self->ready) + { + g_error ("not ready"); + return; + } + + out_port = (GOmxPort *)gst_pad_get_element_private(pad); + + if (G_LIKELY (out_port->enabled)) + { + gpointer obj = g_omx_port_recv (out_port); + + if (G_UNLIKELY (!obj)) + { + GST_WARNING_OBJECT (self, "null buffer: leaving"); + ret = GST_FLOW_WRONG_STATE; + goto leave; + } + + if (G_LIKELY (GST_IS_BUFFER (obj))) + { + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) + { + GstCaps *caps = NULL; + GstStructure *structure; + GValue value = { 0 }; + + caps = gst_pad_get_negotiated_caps (pad); + caps = gst_caps_make_writable (caps); + structure = gst_caps_get_structure (caps, 0); + + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, obj); + gst_buffer_unref (obj); + gst_structure_set_value (structure, "codec_data", &value); + g_value_unset (&value); + + gst_pad_set_caps (pad, caps); + } + else + { + GstBuffer *buf = GST_BUFFER (obj); + ret = bclass->push_buffer (self, buf); + GST_DEBUG_OBJECT (self, "ret=%s", gst_flow_get_name (ret)); + } + } + else if (GST_IS_EVENT (obj)) + { + GST_DEBUG_OBJECT (self, "got eos"); + gst_pad_push_event (pad, obj); + ret = GST_FLOW_UNEXPECTED; + goto leave; + } + + } + +leave: + + self->last_pad_push_return = ret; + + if (gomx->omx_error != OMX_ErrorNone) + { + GST_DEBUG_OBJECT (self, "omx_error=%s", g_omx_error_to_str (gomx->omx_error)); + ret = GST_FLOW_ERROR; + } + + if (ret != GST_FLOW_OK) + { + GST_INFO_OBJECT (self, "pause task, reason: %s", + gst_flow_get_name (ret)); + gst_pad_pause_task (pad); + } + + GST_LOG_OBJECT (self, "end"); + + gst_object_unref (self); +} + +static GstFlowReturn +pad_chain (GstPad *pad, + GstBuffer *buf) +{ + GOmxCore *gomx; + GOmxPort *in_port; + GstOmxBaseFilter2 *self; + GstFlowReturn ret = GST_FLOW_OK; + int i; + + self = GST_OMX_BASE_FILTER2 (GST_OBJECT_PARENT (pad)); + + //printf("INput!!\n"); + PRINT_BUFFER (self, buf); + + gomx = self->gomx; + + GST_LOG_OBJECT (self, "begin: size=%u, state=%d", GST_BUFFER_SIZE (buf), gomx->omx_state); + + if (G_UNLIKELY (gomx->omx_state == OMX_StateLoaded)) + { + g_mutex_lock (self->ready_lock); + + GST_INFO_OBJECT (self, "omx: prepare"); + + /** @todo this should probably go after doing preparations. */ + if (self->omx_setup) + { + self->omx_setup (self); + } + + setup_input_buffer (self, buf); + + setup_ports (self); + + g_omx_core_prepare (self->gomx); + + if (gomx->omx_state == OMX_StateIdle) + { + self->ready = TRUE; + for (i = 0; i < NUM_OUTPUTS; i++) + gst_pad_start_task (self->srcpad[i], output_loop, self->srcpad[i]); + } + + g_mutex_unlock (self->ready_lock); + + if (gomx->omx_state != OMX_StateIdle) + goto out_flushing; + } + + in_port = self->in_port; + + if (G_LIKELY (in_port->enabled)) + { + if (G_UNLIKELY (gomx->omx_state == OMX_StateIdle)) + { + GST_INFO_OBJECT (self, "omx: play"); + g_omx_core_start (gomx); + + if (gomx->omx_state != OMX_StateExecuting) + goto out_flushing; + + /* send buffer with codec data flag */ + if (self->codec_data) + { + GST_BUFFER_FLAG_SET (self->codec_data, GST_BUFFER_FLAG_IN_CAPS); /* just in case */ + g_omx_port_send (in_port, self->codec_data); + } + + } + + if (G_UNLIKELY (gomx->omx_state != OMX_StateExecuting)) + { + GST_ERROR_OBJECT (self, "Whoa! very wrong"); + } + + while (TRUE) + { + gint sent; + + if (self->last_pad_push_return != GST_FLOW_OK || + !(gomx->omx_state == OMX_StateExecuting || + gomx->omx_state == OMX_StatePause)) + { + GST_DEBUG_OBJECT (self, "last_pad_push_return=%d", self->last_pad_push_return); + goto out_flushing; + } + + if (self->input_fields_separately) { + g_omx_port_send_interlaced_fields (in_port, buf, self->second_field_offset); + gst_buffer_unref (buf); + break; + } + + sent = g_omx_port_send (in_port, buf); + + if (G_UNLIKELY (sent < 0)) + { + ret = GST_FLOW_WRONG_STATE; + goto out_flushing; + } + else if (sent < GST_BUFFER_SIZE (buf)) + { + GstBuffer *subbuf = gst_buffer_create_sub (buf, sent, + GST_BUFFER_SIZE (buf) - sent); + gst_buffer_unref (buf); + buf = subbuf; + } + else + { + gst_buffer_unref (buf); + break; + } + } + } + else + { + GST_WARNING_OBJECT (self, "done"); + ret = GST_FLOW_UNEXPECTED; + } + +leave: + + GST_LOG_OBJECT (self, "end"); + + return ret; + + /* special conditions */ +out_flushing: + { + const gchar *error_msg = NULL; + + if (gomx->omx_error) + { + error_msg = "Error from OpenMAX component"; + } + else if (gomx->omx_state != OMX_StateExecuting && + gomx->omx_state != OMX_StatePause) + { + error_msg = "OpenMAX component in wrong state"; + } + + if (error_msg) + { + GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL), (error_msg)); + ret = GST_FLOW_ERROR; + } + + gst_buffer_unref (buf); + + goto leave; + } +} + +static gboolean +pad_event (GstPad *pad, + GstEvent *event) +{ + GstOmxBaseFilter2 *self; + GOmxCore *gomx; + gboolean ret = TRUE; + int i; + + self = GST_OMX_BASE_FILTER2 (GST_OBJECT_PARENT (pad)); + gomx = self->gomx; + + GST_INFO_OBJECT (self, "begin: event=%s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) + { + case GST_EVENT_EOS: + printf ("Recieved EOS event, press <CTRL+C> to terminate pipeline.\n"); + /* if we are init'ed, and there is a running loop; then + * if we get a buffer to inform it of EOS, let it handle the rest + * in any other case, we send EOS */ + if (self->ready && self->last_pad_push_return == GST_FLOW_OK) + { + /***** FIXME: EZSDK OMX componet does not execute FBD callback for an + ETB call when nFlags is set to OMX_BUFFERFLAG_EOS. Because of this + we are not able to trigger EOS on srcpad task. For now disable sending this event + until we get OMX component fixed. */ + #if 0 + if (g_omx_port_send (self->in_port, event) >= 0) + { + gst_event_unref (event); + break; + } + #endif + } + + /* we tried, but it's up to us here */ + for (i = 0; i < NUM_OUTPUTS-1; i++) { + gst_event_ref(event); + ret &= gst_pad_push_event (self->srcpad[i], event); + } + ret &= gst_pad_push_event (self->srcpad[i], event); + break; + + case GST_EVENT_FLUSH_START: + for (i = 0; i < NUM_OUTPUTS-1; i++) { + gst_event_ref(event); + ret &= gst_pad_push_event (self->srcpad[i], event); + } + ret &= gst_pad_push_event (self->srcpad[i], event); + self->last_pad_push_return = GST_FLOW_WRONG_STATE; + + g_omx_core_flush_start (gomx); + + for (i = 0; i < NUM_OUTPUTS; i++) + gst_pad_pause_task (self->srcpad[i]); + + ret = TRUE; + break; + + case GST_EVENT_FLUSH_STOP: + for (i = 0; i < NUM_OUTPUTS-1; i++) { + gst_event_ref(event); + ret &= gst_pad_push_event (self->srcpad[i], event); + } + ret &= gst_pad_push_event (self->srcpad[i], event); + self->last_pad_push_return = GST_FLOW_OK; + + g_omx_core_flush_stop (gomx); + + if (self->ready) + for (i = 0; i < NUM_OUTPUTS; i++) + gst_pad_start_task (self->srcpad[i], output_loop, self->srcpad[i]); + + ret = TRUE; + break; + + case GST_EVENT_NEWSEGMENT: + for (i = 0; i < NUM_OUTPUTS-1; i++) { + self->last_buf_timestamp[i] = GST_CLOCK_TIME_NONE; + gst_event_ref(event); + ret &= gst_pad_push_event (self->srcpad[i], event); + } + self->last_buf_timestamp[i] = GST_CLOCK_TIME_NONE; + ret &= gst_pad_push_event (self->srcpad[i], event); + break; + + default: + for (i = 0; i < NUM_OUTPUTS-1; i++) { + gst_event_ref(event); + ret &= gst_pad_push_event (self->srcpad[i], event); + } + ret &= gst_pad_push_event (self->srcpad[i], event); + break; + } + + GST_LOG_OBJECT (self, "end"); + + return ret; +} + +static gboolean +activate_push (GstPad *pad, + gboolean active) +{ + gboolean result = TRUE; + GstOmxBaseFilter2 *self; + int i; + + self = GST_OMX_BASE_FILTER2 (gst_pad_get_parent (pad)); + + if (active) + { + GST_DEBUG_OBJECT (self, "activate"); + self->last_pad_push_return = GST_FLOW_OK; + + /* we do not start the task yet if the pad is not connected */ + if (gst_pad_is_linked (pad)) + { + if (self->ready) + { + /** @todo link callback function also needed */ + g_omx_port_resume (self->in_port); + for (i = 0; i < NUM_OUTPUTS; i++) + g_omx_port_resume (self->out_port[i]); + + result = gst_pad_start_task (pad, output_loop, pad); + } + } + } + else + { + GST_DEBUG_OBJECT (self, "deactivate"); + + if (self->ready) + { + /** @todo disable this until we properly reinitialize the buffers. */ +#if 0 + /* flush all buffers */ + OMX_SendCommand (self->gomx->omx_handle, OMX_CommandFlush, OMX_ALL, NULL); +#endif + + /* unlock loops */ + g_omx_port_pause (self->in_port); + for (i = 0; i < NUM_OUTPUTS; i++) + g_omx_port_pause (self->out_port[i]); + } + + /* make sure streaming finishes */ + result = gst_pad_stop_task (pad); + } + + gst_object_unref (self); + + return result; +} + +/** + * overrides the default buffer allocation for output port to allow + * pad_alloc'ing from the srcpad + */ +static GstBuffer * +buffer_alloc (GOmxPort *port, gint len) +{ + GstOmxBaseFilter2 *self = port->core->object; + GstBuffer *buf; + GstFlowReturn ret; + int i; + + for (i = 0; i < NUM_OUTPUTS; i++) + if (port == self->out_port[i]) break; + if (i >= NUM_OUTPUTS) return NULL; + +#if 1 + /** @todo remove this check */ + if (G_LIKELY (self->in_port->enabled)) + { + GstCaps *caps = NULL; + + caps = gst_pad_get_negotiated_caps (self->srcpad[i]); + + if (!caps) + { + /** @todo We shouldn't be doing this. */ + GOmxCore *gomx = self->gomx; + GST_WARNING_OBJECT (self, "faking settings changed notification"); + if (gomx->settings_changed_cb) + gomx->settings_changed_cb (gomx); + } + else + { + GST_LOG_OBJECT (self, "caps already fixed: %" GST_PTR_FORMAT, caps); + gst_caps_unref (caps); + } + } +#endif + + ret = gst_pad_alloc_buffer_and_set_caps ( + self->srcpad[i], GST_BUFFER_OFFSET_NONE, + len, GST_PAD_CAPS (self->srcpad[i]), &buf); + + if (ret == GST_FLOW_OK) return buf; + + return NULL; +} + +static void +type_instance_init (GTypeInstance *instance, + gpointer g_class) +{ + GstOmxBaseFilter2 *self; + GstElementClass *element_class; + GstOmxBaseFilter2Class *bclass; + int i; + char srcname[10]; + + element_class = GST_ELEMENT_CLASS (g_class); + bclass = GST_OMX_BASE_FILTER2_CLASS (g_class); + + self = GST_OMX_BASE_FILTER2 (instance); + + GST_LOG_OBJECT (self, "begin"); + + /* GOmx */ + self->gomx = g_omx_core_new (self, g_class); + self->in_port = g_omx_core_get_port (self->gomx, "in", 0); + self->in_port->omx_allocate = TRUE; + self->in_port->share_buffer = FALSE; + + for (i = 0; i < NUM_OUTPUTS; i++) { + sprintf(srcname, "out_%02x", i); + self->out_port[i] = g_omx_core_get_port (self->gomx, srcname, 1+i); + self->out_port[i]->buffer_alloc = buffer_alloc; + self->out_port[i]->omx_allocate = TRUE; + self->out_port[i]->share_buffer = FALSE; + } + self->ready_lock = g_mutex_new (); + + self->sinkpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, "sink"), "sink"); + + gst_pad_set_chain_function (self->sinkpad, bclass->pad_chain); + gst_pad_set_event_function (self->sinkpad, bclass->pad_event); + + gst_element_add_pad (GST_ELEMENT (self), self->sinkpad); + + for (i = 0; i < NUM_OUTPUTS; i++) { + sprintf(srcname, "src_%02x", i); + self->srcpad[i] = + gst_pad_new_from_template (gst_element_class_get_pad_template (element_class, srcname), srcname); + gst_pad_set_activatepush_function (self->srcpad[i], activate_push); + gst_pad_use_fixed_caps (self->srcpad[i]); + gst_element_add_pad (GST_ELEMENT (self), self->srcpad[i]); + } + self->duration = GST_CLOCK_TIME_NONE; + self->input_fields_separately = FALSE; + + GST_LOG_OBJECT (self, "end"); +} + +static void +omx_interface_init (GstImplementsInterfaceClass *klass) +{ +} + +static gboolean +interface_supported (GstImplementsInterface *iface, + GType type) +{ + g_assert (type == GST_TYPE_OMX); + return TRUE; +} + +static void +interface_init (GstImplementsInterfaceClass *klass) +{ + klass->supported = interface_supported; +} + +static void +init_interfaces (GType type) +{ + GInterfaceInfo *iface_info; + GInterfaceInfo *omx_info; + + + iface_info = g_new0 (GInterfaceInfo, 1); + iface_info->interface_init = (GInterfaceInitFunc) interface_init; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, iface_info); + g_free (iface_info); + + omx_info = g_new0 (GInterfaceInfo, 1); + omx_info->interface_init = (GInterfaceInitFunc) omx_interface_init; + + g_type_add_interface_static (type, GST_TYPE_OMX, omx_info); + g_free (omx_info); +} + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter2.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter2.h new file mode 100644 index 0000000..8571bca --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_filter2.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2007-2009 Nokia Corporation. + * + * Author: Felipe Contreras <felipe.contreras@nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef GSTOMX_BASE_FILTER2_H +#define GSTOMX_BASE_FILTER2_H + +#include <gst/gst.h> + +G_BEGIN_DECLS + +#define GST_OMX_BASE_FILTER2(obj) ((GstOmxBaseFilter2 *) (obj)) +#define GST_OMX_BASE_FILTER2_TYPE (gst_omx_base_filter2_get_type ()) +#define GST_OMX_BASE_FILTER2_CLASS(obj) ((GstOmxBaseFilter2Class *) (obj)) +#define GST_OMX_BASE_FILTER2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_OMX_BASE_FILTER2_TYPE, GstOmxBaseFilter2Class)) + +typedef struct GstOmxBaseFilter2 GstOmxBaseFilter2; +typedef struct GstOmxBaseFilter2Class GstOmxBaseFilter2Class; +typedef void (*GstOmxBaseFilter2Cb) (GstOmxBaseFilter2 *self); +typedef void (*GstOmxBaseFilter2PushCb) (GstOmxBaseFilter2 *self, GstBuffer *buf); + +#include "gstomx_util.h" +#include <async_queue.h> + + +struct GstOmxBaseFilter2 +{ + GstElement element; + + GstPad *sinkpad; +#define NUM_OUTPUTS 2 + GstPad *srcpad[NUM_OUTPUTS]; + + GOmxCore *gomx; + GOmxPort *in_port; + GOmxPort *out_port[NUM_OUTPUTS]; + + char *omx_role; + char *omx_component; + char *omx_library; + gboolean ready; + GMutex *ready_lock; + + GstOmxBaseFilter2Cb omx_setup; + GstOmxBaseFilter2PushCb push_cb; + GstFlowReturn last_pad_push_return; + GstBuffer *codec_data; + GstClockTime duration; + GstClockTime last_buf_timestamp[NUM_OUTPUTS]; + + /* Used in deinterlacer kind of components where + one input interlaced input buffer in the input + translates to 2 inputs to omx dei component + */ + gboolean input_fields_separately; + gint second_field_offset; +}; + +struct GstOmxBaseFilter2Class +{ + GstElementClass parent_class; + + GstFlowReturn (*push_buffer) (GstOmxBaseFilter2 *self, GstBuffer *buf); + GstFlowReturn (*pad_chain) (GstPad *pad, GstBuffer *buf); + gboolean (*pad_event) (GstPad *pad, GstEvent *event); +}; + +GType gst_omx_base_filter2_get_type (void); + +G_END_DECLS + +#endif /* GSTOMX_BASE_FILTER2_H */ diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_vfpc2.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_vfpc2.c new file mode 100644 index 0000000..d223e3b --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_vfpc2.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2011-2012 Texas Instruments Inc. + * + * Author: Brijesh Singh <bksingh@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "gstomx_base_vfpc2.h" +#include "gstomx.h" +#include <gst/video/video.h> + +#include <OMX_TI_Index.h> + +#include <string.h> /* for memset */ + +GSTOMX_BOILERPLATE (GstOmxBaseVfpc2, gst_omx_base_vfpc2, GstOmxBaseFilter2, GST_OMX_BASE_FILTER2_TYPE); + +static GstFlowReturn push_buffer (GstOmxBaseFilter2 *self, GstBuffer *buf); + +static gboolean +pad_event (GstPad *pad, GstEvent *event) +{ + GstOmxBaseVfpc2 *self; + GstOmxBaseFilter2 *omx_base; + + self = GST_OMX_BASE_VFPC2 (GST_OBJECT_PARENT (pad)); + omx_base = GST_OMX_BASE_FILTER2 (self); + + GST_INFO_OBJECT (self, "begin: event=%s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) + { + case GST_EVENT_CROP: + { + gst_event_parse_crop (event, &self->top, &self->left, NULL, NULL); + return TRUE; + } + default: + { + return parent_class->pad_event (pad, event); + } + } +} + +static void +type_base_init (gpointer g_class) +{ + GstElementClass *element_class; + GstOmxBaseFilter2Class *bfilter_class = GST_OMX_BASE_FILTER2_CLASS (g_class); + + element_class = GST_ELEMENT_CLASS (g_class); + + bfilter_class->pad_event = pad_event; +} + +static GstFlowReturn +push_buffer (GstOmxBaseFilter2 *omx_base, GstBuffer *buf) +{ + return parent_class->push_buffer (omx_base, buf); +} + +static gint +gstomx_calculate_stride (int width, GstVideoFormat format) +{ + switch (format) + { + case GST_VIDEO_FORMAT_NV12: + return width; + case GST_VIDEO_FORMAT_YUY2: + return width * 2; + default: + GST_ERROR ("unsupported color format"); + } + return -1; +} + +static gboolean +sink_setcaps (GstPad *pad, + GstCaps *caps) +{ + GstStructure *structure; + GstOmxBaseVfpc2 *self; + GstOmxBaseFilter2 *omx_base; + GOmxCore *gomx; + GstVideoFormat format; + + self = GST_OMX_BASE_VFPC2 (GST_PAD_PARENT (pad)); + omx_base = GST_OMX_BASE_FILTER2 (self); + + gomx = (GOmxCore *) omx_base->gomx; + + GST_INFO_OBJECT (self, "setcaps (sink): %" GST_PTR_FORMAT, caps); + + g_return_val_if_fail (caps, FALSE); + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + + structure = gst_caps_get_structure (caps, 0); + + g_return_val_if_fail (structure, FALSE); + + if (!gst_video_format_parse_caps_strided (caps, + &format, &self->in_width, &self->in_height, &self->in_stride)) + { + GST_WARNING_OBJECT (self, "width and/or height is not set in caps"); + return FALSE; + } + + if (!self->in_stride) + { + self->in_stride = gstomx_calculate_stride (self->in_width, format); + } + + { + const GValue *framerate = NULL; + framerate = gst_structure_get_value (structure, "framerate"); + if (framerate) + { + self->framerate_num = gst_value_get_fraction_numerator (framerate); + self->framerate_denom = gst_value_get_fraction_denominator (framerate); + + if (self->framerate_num && self->framerate_denom) { + omx_base->duration = gst_util_uint64_scale_int(GST_SECOND, + gst_value_get_fraction_denominator (framerate), + gst_value_get_fraction_numerator (framerate)); + } + GST_DEBUG_OBJECT (self, "Nominal frame duration =%"GST_TIME_FORMAT, + GST_TIME_ARGS (omx_base->duration)); + } + } + /* check for pixel-aspect-ratio, to set to src caps */ + { + const GValue *v = NULL; + v = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (v) { + self->pixel_aspect_ratio_num = gst_value_get_fraction_numerator (v); + self->pixel_aspect_ratio_denom = gst_value_get_fraction_denominator (v); + } else self->pixel_aspect_ratio_denom = 0; + } + + if (!gst_structure_get_boolean (structure, "interlaced", &self->interlaced)) + self->interlaced = FALSE; + + if (self->sink_setcaps) + self->sink_setcaps (pad, caps); + + return gst_pad_set_caps (pad, caps); +} + +static gboolean +src_setcaps (GstPad *pad, GstCaps *caps) +{ + GstOmxBaseVfpc2 *self; + GstOmxBaseFilter2 *omx_base; + GstVideoFormat format; + GstStructure *structure; + int i; + + self = GST_OMX_BASE_VFPC2 (GST_PAD_PARENT (pad)); + omx_base = GST_OMX_BASE_FILTER2 (self); + structure = gst_caps_get_structure (caps, 0); + + GST_INFO_OBJECT (omx_base, "setcaps (src): %" GST_PTR_FORMAT, caps); + g_return_val_if_fail (caps, FALSE); + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + + for (i=0; i<NUM_OUTPUTS; i++) + if (pad == omx_base->srcpad[i]) break; + if (!(i<NUM_OUTPUTS)) return FALSE; + + if (!gst_video_format_parse_caps_strided (caps, + &format, &self->out_width[i], &self->out_height[i], &self->out_stride[i])) + { + GST_WARNING_OBJECT (self, "width and/or height is not set in caps"); + return FALSE; + } + + if (!self->out_stride[i]) + { + self->out_stride[i] = gstomx_calculate_stride (self->out_width[i], format); + } + + /* save the src caps later needed by omx transport buffer */ + if (omx_base->out_port[i]->caps) + gst_caps_unref (omx_base->out_port[i]->caps); + + omx_base->out_port[i]->caps = gst_caps_copy (caps); + + return TRUE; +} + +static void +omx_setup (GstOmxBaseFilter2 *omx_base) +{ + GstOmxBaseVfpc2 *self; + GOmxCore *gomx; + GOmxPort *port; + int i; + + self = GST_OMX_BASE_VFPC2 (omx_base); + gomx = (GOmxCore *) omx_base->gomx; + + GST_INFO_OBJECT (omx_base, "begin"); + + if (self->omx_setup) + { + self->omx_setup (omx_base); + } + + /* enable input port */ + port = omx_base->in_port; + OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, port->port_index, NULL); + g_sem_down (port->core->port_sem); + + for (i=0; i<NUM_OUTPUTS; i++) { + /* enable output port */ + port = omx_base->out_port[i]; + OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, port->port_index, NULL); + g_sem_down (port->core->port_sem); + } + /* indicate that port is now configured */ + self->port_configured = TRUE; + + GST_INFO_OBJECT (omx_base, "end"); +} + +static void +type_class_init (gpointer g_class, + gpointer class_data) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (g_class); + GST_OMX_BASE_FILTER2_CLASS (g_class)->push_buffer = push_buffer; +} + +static void +type_instance_init (GTypeInstance *instance, + gpointer g_class) +{ + GstOmxBaseFilter2 *omx_base; + GstOmxBaseVfpc2 *self; + char srcname[10]; + int i; + + omx_base = GST_OMX_BASE_FILTER2 (instance); + self = GST_OMX_BASE_VFPC2 (instance); + + omx_base->omx_setup = omx_setup; + self->g_class = g_class; + + gst_pad_set_setcaps_function (omx_base->sinkpad, + GST_DEBUG_FUNCPTR (sink_setcaps)); + for (i=0; i<NUM_OUTPUTS; i++) + gst_pad_set_setcaps_function (omx_base->srcpad[i], + GST_DEBUG_FUNCPTR (src_setcaps)); + + /* free the existing core and ports */ + g_omx_core_free (omx_base->gomx); + g_omx_port_free (omx_base->in_port); + + /* create new core and ports */ + omx_base->gomx = g_omx_core_new (omx_base, self->g_class); + omx_base->in_port = g_omx_core_get_port (omx_base->gomx, "in", OMX_VFPC_INPUT_PORT_START_INDEX); + + omx_base->in_port->omx_allocate = TRUE; + omx_base->in_port->share_buffer = FALSE; + omx_base->in_port->always_copy = FALSE; + omx_base->in_port->port_index = OMX_VFPC_INPUT_PORT_START_INDEX; + + for (i=0; i<NUM_OUTPUTS; i++) { + g_omx_port_free (omx_base->out_port[i]); + sprintf(srcname, "src_%02x", i); + omx_base->out_port[i] = g_omx_core_get_port (omx_base->gomx, "out", + OMX_VFPC_OUTPUT_PORT_START_INDEX + i); + omx_base->out_port[i]->port_index = OMX_VFPC_OUTPUT_PORT_START_INDEX + i; + omx_base->out_port[i]->omx_allocate = TRUE; + omx_base->out_port[i]->share_buffer = FALSE; + omx_base->out_port[i]->always_copy = FALSE; + } +} + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_vfpc2.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_vfpc2.h new file mode 100644 index 0000000..75bcd87 --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_vfpc2.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010-2011 Texas Instruments Inc. + * + * Author: Brijesh Singh <bksingh@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef GSTOMX_BASE_VFPC2_H +#define GSTOMX_BASE_VFPC2_H + +#include <gst/gst.h> + +#include <OMX_TI_Index.h> +#include <OMX_TI_Common.h> +#include <omx_vfpc.h> + +G_BEGIN_DECLS + +#define GST_OMX_BASE_VFPC2(obj) (GstOmxBaseVfpc2 *) (obj) +#define GST_OMX_BASE_VFPC2_TYPE (gst_omx_base_vfpc2_get_type ()) +#define GST_OMX_BASE_VFPC2_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GST_OMX_BASE_VFPC2_TYPE, GstOmxBaseVfpc2Class)) + +typedef struct GstOmxBaseVfpc2 GstOmxBaseVfpc2; +typedef struct GstOmxBaseVfpc2Class GstOmxBaseVfpc2Class; + +#include "gstomx_base_filter2.h" + +struct GstOmxBaseVfpc2 +{ + GstOmxBaseFilter2 omx_base; + + gint framerate_num; + gint framerate_denom; + gboolean port_configured; + GstPadSetCapsFunction sink_setcaps; + gint in_width, in_height, in_stride; + gint out_width[NUM_OUTPUTS], out_height[NUM_OUTPUTS], out_stride[NUM_OUTPUTS]; + gint left, top; + GstOmxBaseFilter2Cb omx_setup; + gpointer g_class; + gint pixel_aspect_ratio_num; + gint pixel_aspect_ratio_denom; + gboolean interlaced; +}; + +struct GstOmxBaseVfpc2Class +{ + GstOmxBaseFilter2Class parent_class; +}; + +GType gst_omx_base_vfpc2_get_type (void); + +G_END_DECLS + +#endif /* GSTOMX_BASE_VFPC2_H */ + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_videodec.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_videodec.c index a7428b6..106d5e4 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_videodec.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_base_videodec.c @@ -21,11 +21,13 @@ #include "gstomx_base_videodec.h" #include "gstomx.h" +#include "gstomx_buffertransport.h" #include <gst/video/video.h> #ifdef USE_OMXTICORE # include <OMX_TI_Index.h> +# include <OMX_TI_Common.h> #endif #include <string.h> /* for memset */ @@ -66,7 +68,7 @@ static void type_class_init (gpointer g_class, gpointer class_data) { - GST_OMX_BASE_FILTER_CLASS (g_class)->push_buffer = push_buffer; + //GST_OMX_BASE_FILTER_CLASS (g_class)->push_buffer = push_buffer; } static GstFlowReturn @@ -145,9 +147,6 @@ sink_setcaps (GstPad *pad, width, height); return FALSE; } - if(width % 16) - width = ((width/16) + 1)*16; - { const GValue *framerate = NULL; framerate = gst_structure_get_value (structure, "framerate"); @@ -276,9 +275,9 @@ src_getcaps (GstPad *pad) } else { - gst_structure_set (struc, - "rowstride", G_TYPE_INT, param.format.video.nStride, - NULL); + gst_structure_set (struc, + "rowstride", G_TYPE_INT, param.format.video.nStride, + NULL); } } @@ -460,6 +459,35 @@ omx_setup (GstOmxBaseFilter *omx_base) GST_INFO_OBJECT (omx_base, "end"); } +static void push_cb (GstOmxBaseFilter *omx_base, GstBuffer *buf) +{ + GstOmxBaseVideoDec *self; + OMX_BUFFERHEADERTYPE *omxbuffer; + GstCaps *caps, tmp; + GstStructure *structure; + gboolean i; + + self = GST_OMX_BASE_VIDEODEC (omx_base); + omxbuffer = GST_GET_OMXBUFFER(buf); + + /* Change interlaced flag in srcpad caps if decoder differs with + what is already got from the upstream element */ + i = (0 != (omxbuffer->nFlags & + OMX_TI_BUFFERFLAG_VIDEO_FRAME_TYPE_INTERLACE)); + if (i != self->interlaced) { + caps = gst_caps_copy(GST_PAD_CAPS(omx_base->srcpad)); + self->interlaced = i; + structure = gst_caps_get_structure (caps, 0); + if (structure) { + gst_structure_set (structure, + "interlaced", G_TYPE_BOOLEAN, self->interlaced, NULL); + } + gst_pad_set_caps(omx_base->srcpad, caps); + if (GST_BUFFER_CAPS(buf)) gst_caps_unref(GST_BUFFER_CAPS(buf)); + GST_BUFFER_CAPS(buf) = caps; + } +} + static void type_instance_init (GTypeInstance *instance, gpointer g_class) @@ -469,6 +497,7 @@ type_instance_init (GTypeInstance *instance, omx_base = GST_OMX_BASE_FILTER (instance); omx_base->omx_setup = omx_setup; + omx_base->push_cb = push_cb; omx_base->gomx->settings_changed_cb = settings_changed_cb; diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.c index b9837be..68f0257 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.c @@ -98,13 +98,16 @@ release_buffer (GOmxPort *port, OMX_BUFFERHEADERTYPE *omx_buffer) break; } } +#include <sys/time.h> static void gst_omxbuffertransport_finalize(GstBuffer *gstbuffer) { GstOmxBufferTransport *self = GST_OMXBUFFERTRANSPORT(gstbuffer); int ii; - GST_LOG("begin\n"); + GST_LOG("begin\n"); + static guint64 beftime = 0; + if(self->omxbuffer) release_buffer (self->port, self->omxbuffer); for(ii = 0; ii < self->numAdditionalHeaders; ii++) { @@ -112,10 +115,27 @@ static void gst_omxbuffertransport_finalize(GstBuffer *gstbuffer) if(self->addHeader[ii]) release_buffer(self->port,self->addHeader[ii]); } - + if(self->addHeader) { + free(self->addHeader); + //printf("free\n"); + } + if(self->parent) + gst_buffer_unref(self->parent); + + if(self->bufSem) { + struct timeval tv; + guint64 afttime; + gettimeofday(&tv, NULL); + afttime = (tv.tv_sec * 1000000 + tv.tv_usec); + //printf("sem up:%lld\n",(afttime-beftime) ); + beftime = afttime; + g_sem_up(self->bufSem); + } + + self->addHeader = NULL; self->omxbuffer = NULL; self->port = NULL; - + self->parent = NULL; /* Call GstBuffer's finalize routine, so our base class can do it's cleanup * as well. If we don't do this, we'll have a memory leak that is very * difficult to track down. @@ -149,18 +169,56 @@ GstBuffer* gst_omxbuffertransport_new (GOmxPort *port, OMX_BUFFERHEADERTYPE *buf tdt_buf->numAdditionalHeaders = 0; tdt_buf->addHeader = NULL; + tdt_buf->parent = NULL; + tdt_buf->bufSem = NULL; GST_LOG("end new\n"); return GST_BUFFER(tdt_buf); } +GstBuffer* gst_omxbuffertransport_clone (GstBuffer *parent, GOmxPort *port) +{ + GstOmxBufferTransport *tdt_buf; + tdt_buf = (GstOmxBufferTransport*) + gst_mini_object_new(GST_TYPE_OMXBUFFERTRANSPORT); + + g_return_val_if_fail(tdt_buf != NULL, NULL); + + GST_BUFFER_SIZE(tdt_buf) = GST_BUFFER_SIZE(parent); + GST_BUFFER_DATA(tdt_buf) = GST_BUFFER_DATA(parent); + GST_BUFFER_CAPS(GST_BUFFER (tdt_buf)) = gst_caps_ref (GST_BUFFER_CAPS(parent)); + GST_BUFFER_TIMESTAMP(tdt_buf) = GST_BUFFER_TIMESTAMP(parent); + GST_BUFFER_DURATION(tdt_buf) = GST_BUFFER_DURATION(parent); + + if (GST_BUFFER_DATA(tdt_buf) == NULL) { + gst_mini_object_unref(GST_MINI_OBJECT(tdt_buf)); + return NULL; + } + + tdt_buf->omxbuffer = NULL; + tdt_buf->port = port; + tdt_buf->numAdditionalHeaders = 0; + tdt_buf->addHeader = NULL; + tdt_buf->bufSem = NULL; + tdt_buf->parent = parent; + + GST_LOG("end new\n"); + + return GST_BUFFER(tdt_buf); + +} + + void gst_omxbuffertransport_set_additional_headers (GstOmxBufferTransport *self ,guint numHeaders,OMX_BUFFERHEADERTYPE **buffer) { int ii; if(numHeaders == 0) return; + + if(self->addHeader) + free(self->addHeader); self->addHeader = malloc(numHeaders*sizeof(OMX_BUFFERHEADERTYPE *)); @@ -173,4 +231,11 @@ void gst_omxbuffertransport_set_additional_headers (GstOmxBufferTransport *self return ; } +void gst_omxbuffertransport_set_bufsem (GstOmxBufferTransport *self ,GSem *sem) +{ + self->bufSem = sem; + return ; +} + + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.h index 74f1416..5f1c0e9 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_buffertransport.h @@ -61,6 +61,8 @@ struct _GstOmxBufferTransport { GOmxPort *port; guint numAdditionalHeaders; OMX_BUFFERHEADERTYPE **addHeader; + GstBuffer *parent; + GSem *bufSem; }; struct _GstOmxBufferTransportClass { diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_deiscaler.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_deiscaler.c new file mode 100644 index 0000000..3ceb208 --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_deiscaler.c @@ -0,0 +1,403 @@ +/* + * Copyright (C) 2011-2012 Texas Instruments Inc. + * + * Author: Brijesh Singh <bksingh@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "gstomx_deiscaler.h" +#include "gstomx.h" + + +GSTOMX_BOILERPLATE (GstOmxMDeiScaler, gst_omx_mdeiscaler, GstOmxBaseVfpc2, GST_OMX_BASE_VFPC2_TYPE); +GSTOMX_BOILERPLATE (GstOmxHDeiScaler, gst_omx_hdeiscaler, GstOmxBaseVfpc2, GST_OMX_BASE_VFPC2_TYPE); + +static GstStaticPadTemplate sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV_STRIDED ( + "{NV12}", "[ 0, max ]")) + ); + +static GstStaticPadTemplate src_template_yuv2 = + GST_STATIC_PAD_TEMPLATE ("src_00", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV_STRIDED ( "{YUY2}", "[ 0, max ]" )) + ); + +static GstStaticPadTemplate src_template_nv12 = + GST_STATIC_PAD_TEMPLATE ("src_01", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV_STRIDED ( + "{NV12}", "[ 0, max ]")) + ); + +#define YUV2_OUTPUT_IDX 0 +#define NV12_OUTPUT_IDX 1 + +static const guint32 src_fourcc_list[NUM_OUTPUTS] = { + GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), + GST_MAKE_FOURCC ('N', 'V', '1', '2') +}; + +static const OMX_COLOR_FORMATTYPE omx_color_format_list[NUM_OUTPUTS] = { + OMX_COLOR_FormatYCbYCr, + OMX_COLOR_FormatYUV420SemiPlanar +}; + +static const double buffersize_multiplier_list[NUM_OUTPUTS] = { 1, 1.5 }; +static const int rowstride_multiplier_list[NUM_OUTPUTS] = { 2, 1 }; + +static void +type_base_init (gpointer g_class) +{ + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (g_class); + + { + GstElementDetails details; + + details.longname = "OpenMAX IL for OMX.TI.VPSSM3.VFPC.DEIMDUALOUT component"; + details.klass = "Filter"; + details.description = "Deinterlace and Scale video using VPSS Scaler module "; + details.author = "Harinarayan Bhatta"; + + gst_element_class_set_details (element_class, &details); + } + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template_nv12)); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template_yuv2)); +} + +static GstCaps* +create_src_caps (GstOmxBaseFilter2 *omx_base, int idx) +{ + GstCaps *caps; + GstOmxBaseVfpc2 *self; + int width, height, rowstride; + GstStructure *struc; + + self = GST_OMX_BASE_VFPC2 (omx_base); + caps = gst_pad_peer_get_caps (omx_base->srcpad[idx]); + + width = self->in_width; + height = self->in_height; + rowstride = 0; + + if ((NULL != caps) && (!gst_caps_is_empty (caps)) && (0 != gst_caps_get_size (caps))) + { + GstStructure *s; + + s = gst_caps_get_structure (caps, 0); + + if (!(gst_structure_get_int (s, "width", &width) && + gst_structure_get_int (s, "height", &height))) { + width = self->in_width; + height = self->in_height; + } else + gst_structure_get_int (s, "rowstride", &rowstride); + } + /* Workaround: Make width multiple of 16, otherwise, scaler crashes */ + width = (width+15) & 0xFFFFFFF0; + + if (caps) gst_caps_unref (caps); + + caps = gst_caps_new_empty (); + if (rowstride) { + struc = gst_structure_new (("video/x-raw-yuv-strided"), + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "rowstride", G_TYPE_INT, rowstride, + "format", GST_TYPE_FOURCC, src_fourcc_list[idx], + NULL); + } else { + struc = gst_structure_new (("video/x-raw-yuv"), + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "format", GST_TYPE_FOURCC, src_fourcc_list[idx], + NULL); + } + + if (self->framerate_denom) + { + gst_structure_set (struc, + "framerate", GST_TYPE_FRACTION, self->framerate_num, self->framerate_denom, NULL); + } + + if (self->pixel_aspect_ratio_denom) + { + gst_structure_set (struc, + "pixel-aspect-ratio", GST_TYPE_FRACTION, self->pixel_aspect_ratio_num, + self->pixel_aspect_ratio_denom, NULL); + } + + gst_structure_set (struc, + "interlaced", G_TYPE_BOOLEAN, FALSE, NULL); + + + gst_caps_append_structure (caps, struc); + + return caps; +} + +static void +omx_setup (GstOmxBaseFilter2 *omx_base) +{ + GOmxCore *gomx; + OMX_ERRORTYPE err; + OMX_PARAM_PORTDEFINITIONTYPE paramPort; + OMX_PARAM_BUFFER_MEMORYTYPE memTypeCfg; + OMX_PARAM_VFPC_NUMCHANNELPERHANDLE numChannels; + OMX_CONFIG_VIDCHANNEL_RESOLUTION chResolution; + OMX_CONFIG_ALG_ENABLE algEnable; + OMX_CONFIG_SUBSAMPLING_FACTOR sSubSamplinginfo = {NULL}; + + GstOmxBaseVfpc2 *self; + int i, x, y, shift = 0; + + gomx = (GOmxCore *) omx_base->gomx; + self = GST_OMX_BASE_VFPC2 (omx_base); + + GST_LOG_OBJECT (self, "begin"); + + omx_base->input_fields_separately = self->interlaced; + + if (omx_base->duration != GST_CLOCK_TIME_NONE) { + omx_base->duration *= (GST_OMX_DEISCALER(self))->framerate_divisor; + self->framerate_denom *= (GST_OMX_DEISCALER(self))->framerate_divisor; + if (omx_base->input_fields_separately) { + // Halve the duration of output frame + omx_base->duration = omx_base->duration/2; + self->framerate_num *= 2; + } + } + + /* set the output cap */ + for (i=0 ; i<NUM_OUTPUTS; i++) + gst_pad_set_caps (omx_base->srcpad[i], create_src_caps (omx_base, i)); + + /* Setting Memory type at input port to Raw Memory */ + GST_LOG_OBJECT (self, "Setting input port to Raw memory"); + + _G_OMX_INIT_PARAM (&memTypeCfg); + memTypeCfg.nPortIndex = omx_base->in_port->port_index; + memTypeCfg.eBufMemoryType = OMX_BUFFER_MEMORY_DEFAULT; + err = OMX_SetParameter (gomx->omx_handle, OMX_TI_IndexParamBuffMemType, &memTypeCfg); + + if (err != OMX_ErrorNone) + return; + + /* Setting Memory type at output port to Raw Memory */ + GST_LOG_OBJECT (self, "Setting output port to Raw memory"); + + for (i=0 ; i<NUM_OUTPUTS; i++) { + _G_OMX_INIT_PARAM (&memTypeCfg); + memTypeCfg.nPortIndex = omx_base->out_port[i]->port_index; + memTypeCfg.eBufMemoryType = OMX_BUFFER_MEMORY_DEFAULT; + err = OMX_SetParameter (gomx->omx_handle, OMX_TI_IndexParamBuffMemType, &memTypeCfg); + + if (err != OMX_ErrorNone) + return; + } + + if (self->interlaced) shift = 1; + /* Input port configuration. */ + GST_LOG_OBJECT (self, "Setting port definition (input)"); + + G_OMX_PORT_GET_DEFINITION (omx_base->in_port, ¶mPort); + paramPort.format.video.nFrameWidth = self->in_width; + paramPort.format.video.nFrameHeight = self->in_height >> shift; + paramPort.format.video.nStride = self->in_stride; + paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + paramPort.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + paramPort.nBufferSize = self->in_stride * self->in_height * 1.5; + paramPort.nBufferAlignment = 0; + paramPort.bBuffersContiguous = 0; + G_OMX_PORT_SET_DEFINITION (omx_base->in_port, ¶mPort); + g_omx_port_setup (omx_base->in_port, ¶mPort); + + /* Output port configuration. */ + GST_LOG_OBJECT (self, "Setting port definition (output)"); + + for (i=0 ; i<NUM_OUTPUTS; i++) { + G_OMX_PORT_GET_DEFINITION (omx_base->out_port[i], ¶mPort); + paramPort.format.video.nFrameWidth = self->out_width[i]; + paramPort.format.video.nFrameHeight = self->out_height[i]; + paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + paramPort.format.video.nStride = self->out_stride[i]; + paramPort.format.video.eColorFormat = omx_color_format_list[i]; + paramPort.nBufferSize = self->out_stride[i] * self->out_height[i] * buffersize_multiplier_list[i]; + paramPort.nBufferCountActual = 8; + paramPort.nBufferAlignment = 0; + paramPort.bBuffersContiguous = 0; + G_OMX_PORT_SET_DEFINITION (omx_base->out_port[i], ¶mPort); + g_omx_port_setup (omx_base->out_port[i], ¶mPort); + } + + /* Set number of channles */ + GST_LOG_OBJECT (self, "Setting number of channels"); + + _G_OMX_INIT_PARAM (&numChannels); + numChannels.nNumChannelsPerHandle = 1; + err = OMX_SetParameter (gomx->omx_handle, + (OMX_INDEXTYPE) OMX_TI_IndexParamVFPCNumChPerHandle, &numChannels); + + if (err != OMX_ErrorNone) + return; + + /* Set input channel resolution */ + GST_LOG_OBJECT (self, "Setting channel resolution (input)"); + + _G_OMX_INIT_PARAM (&chResolution); + chResolution.Frm0Width = self->in_width; + chResolution.Frm0Height = self->in_height >> shift; + chResolution.Frm0Pitch = self->in_stride; + chResolution.Frm1Width = 0; + chResolution.Frm1Height = 0; + chResolution.Frm1Pitch = 0; + chResolution.FrmStartX = x; + chResolution.FrmStartY = y; + chResolution.FrmCropWidth = self->in_width; + chResolution.FrmCropHeight = self->in_height >> shift; + chResolution.eDir = OMX_DirInput; + chResolution.nChId = 0; + err = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVidChResolution, &chResolution); + + if (err != OMX_ErrorNone) + return; + +#if 1 + _G_OMX_INIT_PARAM(&sSubSamplinginfo); + sSubSamplinginfo.nSubSamplingFactor = (GST_OMX_DEISCALER(self))->framerate_divisor; + err = OMX_SetConfig ( gomx->omx_handle, ( OMX_INDEXTYPE ) + ( OMX_TI_IndexConfigSubSamplingFactor ), + &sSubSamplinginfo ); + if (err != OMX_ErrorNone) + return; +#endif + + /* Set output channel resolution */ + GST_LOG_OBJECT (self, "Setting channel resolution (output)"); + + _G_OMX_INIT_PARAM (&chResolution); + chResolution.Frm0Width = self->out_width[0]; + chResolution.Frm0Height = self->out_height[0]; + chResolution.Frm0Pitch = self->out_stride[0]; + chResolution.Frm1Width = self->out_width[1]; + chResolution.Frm1Height = self->out_height[1]; + chResolution.Frm1Pitch = self->out_stride[1]; + chResolution.FrmStartX = 0; + chResolution.FrmStartY = 0; + chResolution.FrmCropWidth = 0; + chResolution.FrmCropHeight = 0; + chResolution.eDir = OMX_DirOutput; + chResolution.nChId = 0; + err = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVidChResolution, &chResolution); + + if (err != OMX_ErrorNone) + return; + + _G_OMX_INIT_PARAM (&algEnable); + algEnable.nPortIndex = 0; + algEnable.nChId = 0; + algEnable.bAlgBypass = (self->interlaced)?OMX_FALSE:OMX_TRUE; + + err = OMX_SetConfig (gomx->omx_handle, (OMX_INDEXTYPE) OMX_TI_IndexConfigAlgEnable, &algEnable); + + if (err != OMX_ErrorNone) + return; +} + +enum +{ + ARG_0, + ARG_FRAMERATE_DIV, +}; + +static void +set_property (GObject *obj, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case ARG_FRAMERATE_DIV: + (GST_OMX_DEISCALER(obj))->framerate_divisor = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *obj, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case ARG_FRAMERATE_DIV: + g_value_set_uint (value, (GST_OMX_DEISCALER(obj))->framerate_divisor); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } +} + +static void +type_class_init (gpointer g_class, + gpointer class_data) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (g_class); + gobject_class->set_property = set_property; + gobject_class->get_property = get_property; + + g_object_class_install_property (gobject_class, ARG_FRAMERATE_DIV, + g_param_spec_uint ("framerate-divisor", "Output framerate divisor", + "Output framerate = (2 * input_framerate) / framerate_divisor", + 1, 60, 1, G_PARAM_READWRITE)); +} + +static void +type_instance_init (GTypeInstance *instance, + gpointer g_class) +{ + GstOmxBaseVfpc2 *self; + + self = GST_OMX_BASE_VFPC2 (instance); + + self->omx_setup = omx_setup; + + (GST_OMX_DEISCALER(instance))->framerate_divisor = 1; +} + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_deiscaler.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_deiscaler.h new file mode 100644 index 0000000..35dd588 --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_deiscaler.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2011-2012 Texas Instruments Inc. + * + * Author: Brijesh Singh <bksingh@ti.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef GSTOMX_DEISCALER_H +#define GSTOMX_DEISCALER_H + +#include <gst/gst.h> + +G_BEGIN_DECLS + +#define GST_OMX_DEISCALER(obj) (struct GstOmxDeiScaler *) (obj) +// #define GST_OMX_DEISCALER_TYPE (gst_omx_deiscaler_get_type ()) + +typedef struct GstOmxDeiScaler GstOmxMDeiScaler; +typedef struct GstOmxDeiScalerClass GstOmxMDeiScalerClass; +typedef struct GstOmxDeiScaler GstOmxHDeiScaler; +typedef struct GstOmxDeiScalerClass GstOmxHDeiScalerClass; + +#include "gstomx_base_vfpc2.h" + +struct GstOmxDeiScaler +{ + GstOmxBaseVfpc2 omx_base; + gint framerate_divisor; +}; + +struct GstOmxDeiScalerClass +{ + GstOmxBaseVfpc2Class parent_class; +}; + +GType gst_omx_hdeiscaler_get_type (void); +GType gst_omx_mdeiscaler_get_type (void); + +G_END_DECLS + +#endif /* GSTOMX_DEISCALER_H */ diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264dec.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264dec.c index d59a278..4e4cbe3 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264dec.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264dec.c @@ -99,12 +99,12 @@ initialize_port (GstOmxBaseFilter *omx_base) height = self->extendedParams.height; paramPort.nPortIndex = 1; - paramPort.nBufferCountActual = 20;//15;//output_buffer_count + paramPort.nBufferCountActual = 8;//15;//output_buffer_count paramPort.format.video.nFrameWidth = width; paramPort.format.video.nFrameHeight = height; paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; paramPort.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; - paramPort.format.video.xFramerate = (60) << 16; + paramPort.format.video.xFramerate = (30) << 16; GST_DEBUG_OBJECT (self, "nFrameWidth = %ld, nFrameHeight = %ld, nBufferCountActual = %ld", paramPort.format.video.nFrameWidth, paramPort.format.video.nFrameHeight, @@ -112,11 +112,12 @@ initialize_port (GstOmxBaseFilter *omx_base) GST_DEBUG_OBJECT (self, "G_OMX_PORT_SET_DEFINITION (output)"); G_OMX_PORT_SET_DEFINITION (omx_base->out_port, ¶mPort); - +#if 0 G_OMX_PORT_GET_DEFINITION (omx_base->in_port, ¶mPort); //paramPort.nBufferCountActual = 8; - paramPort.format.video.xFramerate = (60) << 16; + // paramPort.format.video.xFramerate = (30) << 16; G_OMX_PORT_SET_DEFINITION (omx_base->in_port, ¶mPort); +#endif #if 0 port = g_omx_core_get_port (gomx, "input", 0); diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c index 82a2d65..6d4e9c5 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.c @@ -3,6 +3,9 @@ * * Author: Felipe Contreras <felipe.contreras@nokia.com> * + * Modified by: David Soto <david.soto@ridgerun.com> + * Copyright (C) 2011 RidgeRun + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation @@ -21,6 +24,8 @@ #include "gstomx_h264enc.h" #include "gstomx.h" +#include <OMX_TI_Index.h> +#include <OMX_TI_Video.h> #include <string.h> /* for memset */ @@ -32,11 +37,18 @@ enum ARG_BYTESTREAM, ARG_PROFILE, ARG_LEVEL, + ARG_I_PERIOD, + ARG_IDR_PERIOD, + ARG_FORCE_IDR, + ARG_ENCODING_PRESET, + ARG_RATECONTROL_PRESET, }; #define DEFAULT_BYTESTREAM FALSE -#define DEFAULT_PROFILE OMX_VIDEO_AVCProfileHigh -#define DEFAULT_LEVEL OMX_VIDEO_AVCLevel4 +#define DEFAULT_PROFILE OMX_VIDEO_AVCProfileBaseline +#define DEFAULT_LEVEL OMX_VIDEO_AVCLevel42 +#define DEFAULT_ENCODE_PRESET OMX_Video_Enc_High_Speed_Med_Quality +#define DEFAULT_RATECONTROL_PRESET OMX_Video_RC_Low_Delay #define GST_TYPE_OMX_VIDEO_AVCPROFILETYPE (gst_omx_video_avcprofiletype_get_type ()) static GType @@ -99,6 +111,54 @@ gst_omx_video_avcleveltype_get_type () return type; } +#define GST_TYPE_OMX_VIDEO_ENCODE_PRESETTYPE (gst_omx_video_enocdepreset_get_type ()) +static GType +gst_omx_video_enocdepreset_get_type () +{ + static GType type = 0; + + if (!type) + { + static const GEnumValue vals[] = + { + {OMX_Video_Enc_High_Quality, "High Quality", "hq"}, + {OMX_Video_Enc_User_Defined, "User Defined", "user"}, + {OMX_Video_Enc_High_Speed_Med_Quality, "High Speed Med Qual", "hsmq"}, + {OMX_Video_Enc_Med_Speed_Med_Quality, "Med Speed Med Qaul", "msmq"}, + {OMX_Video_Enc_Med_Speed_High_Quality, "Med Speed High Qaul", "mshq"}, + {OMX_Video_Enc_High_Speed, "High Speed", "hs"}, + {0, NULL, NULL }, + }; + + type = g_enum_register_static ("GstOmxVideoEncoderPreset", vals); + } + + return type; +} + +#define GST_TYPE_OMX_VIDEO_RATECONTROL_PRESETTYPE (gst_omx_video_ratecontrolpreset_get_type ()) +static GType +gst_omx_video_ratecontrolpreset_get_type () +{ + static GType type = 0; + + if (!type) + { + static const GEnumValue vals[] = + { + {OMX_Video_RC_Low_Delay, "Low Delay", "low-delay"}, + {OMX_Video_RC_Storage, "Storage", "storage"}, + {OMX_Video_RC_Twopass, "Two Pass", "two-pass"}, + {OMX_Video_RC_None, "none", "none"}, + {0, NULL, NULL }, + }; + + type = g_enum_register_static ("GstOmxVideoRateControlPreset", vals); + } + + return type; +} + static GstCaps * generate_src_template (void) { @@ -108,6 +168,8 @@ generate_src_template (void) "width", GST_TYPE_INT_RANGE, 16, 4096, "height", GST_TYPE_INT_RANGE, 16, 4096, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, + "stream-format", G_TYPE_STRING, "byte-stream", + "alignment", G_TYPE_STRING, "au", NULL); return caps; @@ -150,11 +212,9 @@ set_property (GObject *obj, { GstOmxBaseFilter *omx_base; GstOmxH264Enc *self; - GOmxCore *gomx; omx_base = GST_OMX_BASE_FILTER (obj); self = GST_OMX_H264ENC (obj); - gomx = (GOmxCore*) omx_base->gomx; switch (prop_id) { @@ -162,15 +222,14 @@ set_property (GObject *obj, self->bytestream = g_value_get_boolean (value); break; case ARG_PROFILE: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; - GOmxCore *gomx; OMX_ERRORTYPE error_val = OMX_ErrorNone; - gomx = (GOmxCore *) omx_base->gomx; _G_OMX_INIT_PARAM (&tProfileLevel); tProfileLevel.nPortIndex = omx_base->out_port->port_index; - error_val = OMX_GetParameter (gomx->omx_handle, + error_val = OMX_GetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); @@ -178,22 +237,25 @@ set_property (GObject *obj, GST_DEBUG_OBJECT (self, "Profile: param=%d", (gint)tProfileLevel.eProfile); - error_val = OMX_SetParameter (gomx->omx_handle, + error_val = OMX_SetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); break; } + #else + self->profile = g_value_get_enum(value); + break; + #endif case ARG_LEVEL: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; - GOmxCore *gomx; OMX_ERRORTYPE error_val = OMX_ErrorNone; - gomx = (GOmxCore *) omx_base->gomx; _G_OMX_INIT_PARAM (&tProfileLevel); tProfileLevel.nPortIndex = omx_base->out_port->port_index; - error_val = OMX_GetParameter (gomx->omx_handle, + error_val = OMX_GetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); @@ -201,12 +263,101 @@ set_property (GObject *obj, GST_DEBUG_OBJECT (self, "Level: param=%d", (gint)tProfileLevel.eLevel); - error_val = OMX_SetParameter (gomx->omx_handle, + error_val = OMX_SetParameter (g_omx_core_get_handle (omx_base->gomx), OMX_IndexParamVideoProfileLevelCurrent, &tProfileLevel); g_assert (error_val == OMX_ErrorNone); break; } + #else + self->level = g_value_get_enum(value); + break; + #endif + case ARG_I_PERIOD: + #if 0 + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD avcIntraPeriod; + OMX_ERRORTYPE error_val = OMX_ErrorNone; + + _G_OMX_INIT_PARAM (&avcIntraPeriod); + avcIntraPeriod.nPortIndex = omx_base->out_port->port_index; + error_val = OMX_GetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoAVCIntraPeriod, + (OMX_PTR)&avcIntraPeriod); + g_assert (error_val == OMX_ErrorNone); + avcIntraPeriod.nPFrames = g_value_get_uint (value); + + if(value>0) + { + error_val = OMX_SetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoAVCIntraPeriod, + &avcIntraPeriod); + } + g_assert (error_val == OMX_ErrorNone); + break; + } + #else + self->i_period = g_value_get_uint (value); + break; + #endif + case ARG_IDR_PERIOD: + { + self->idr_period = g_value_get_uint (value); + break; + } + case ARG_FORCE_IDR: + { + self->force_idr = g_value_get_boolean (value); + break; + } + case ARG_ENCODING_PRESET: + { + #if 0 + OMX_ERRORTYPE error_val = OMX_ErrorNone; + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + _G_OMX_INIT_PARAM(&tEncoderPreset); + tEncoderPreset.nPortIndex = omx_base->out_port->port_index; + + error_val = + OMX_GetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + + tEncoderPreset.eEncodingModePreset = g_value_get_enum (value); + error_val = OMX_SetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + #else + self->encodingPreset = g_value_get_enum(value); + #endif + break; + } + case ARG_RATECONTROL_PRESET: + { + #if 0 + OMX_ERRORTYPE error_val = OMX_ErrorNone; + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + _G_OMX_INIT_PARAM(&tEncoderPreset); + tEncoderPreset.nPortIndex = omx_base->out_port->port_index; + + error_val = + OMX_GetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + + tEncoderPreset.eRateControlPreset = g_value_get_enum (value); + error_val = OMX_SetParameter(g_omx_core_get_handle (omx_base->gomx), + OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + g_assert (error_val == OMX_ErrorNone); + #else + self->ratecontrolPreset = g_value_get_enum(value); + #endif + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -231,6 +382,7 @@ get_property (GObject *obj, g_value_set_boolean (value, self->bytestream); break; case ARG_PROFILE: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; GOmxCore *gomx; @@ -250,7 +402,12 @@ get_property (GObject *obj, break; } + #else + g_value_set_enum(value, self->profile); + break; + #endif case ARG_LEVEL: + #if 0 { OMX_VIDEO_PARAM_PROFILELEVELTYPE tProfileLevel; GOmxCore *gomx; @@ -270,6 +427,82 @@ get_property (GObject *obj, break; } + #else + g_value_set_enum(value, self->level); + break; + #endif + case ARG_I_PERIOD: + #if 0 + { + OMX_VIDEO_CONFIG_AVCINTRAPERIOD avcIntraPeriod; + GOmxCore *gomx; + + gomx = (GOmxCore *) omx_base->gomx; + _G_OMX_INIT_PARAM (&avcIntraPeriod); + avcIntraPeriod.nPortIndex = omx_base->out_port->port_index; + OMX_GetConfig (gomx->omx_handle, + OMX_IndexConfigVideoAVCIntraPeriod, + &avcIntraPeriod); + g_value_set_uint (value, (gint)avcIntraPeriod.nPFrames); + + break; + } + #else + g_value_set_uint(value, self->i_period); + break; + #endif + case ARG_IDR_PERIOD: + { + g_value_set_uint (value, self->idr_period); + + break; + } + case ARG_FORCE_IDR: + { + g_value_set_boolean (value, self->force_idr); + + break; + } + case ARG_ENCODING_PRESET: + { + #if 0 + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + GOmxCore *gomx; + OMX_ERRORTYPE error_val = OMX_ErrorNone; + + gomx = (GOmxCore *) omx_base->gomx; + error_val = OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + + g_value_set_enum (value, tEncoderPreset.eEncodingModePreset); + + GST_DEBUG_OBJECT (self, "Encoding Preset: param=%d", + (gint)tEncoderPreset.eEncodingModePreset); + #else + g_value_set_enum(value, self->encodingPreset); + #endif + break; + } + case ARG_RATECONTROL_PRESET: + { + #if 0 + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + GOmxCore *gomx; + OMX_ERRORTYPE error_val = OMX_ErrorNone; + + gomx = (GOmxCore *) omx_base->gomx; + error_val = OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, + &tEncoderPreset); + + g_value_set_enum (value, tEncoderPreset.eRateControlPreset); + + GST_DEBUG_OBJECT (self, "RateControl Preset: param=%d", + (gint)tEncoderPreset.eRateControlPreset); + #else + g_value_set_enum(value, self->ratecontrolPreset); + #endif + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -304,8 +537,73 @@ type_class_init (gpointer g_class, GST_TYPE_OMX_VIDEO_AVCLEVELTYPE, DEFAULT_LEVEL, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_I_PERIOD, + g_param_spec_uint ("i-period", "Specifies periodicity of I frames", + "Specifies periodicity of I frames (0:Disable)", + 0, G_MAXINT32, 90, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_IDR_PERIOD, + g_param_spec_uint ("force-idr-period", "Specifies periodicity of IDR frames", + "Specifies periodicity of IDR frames (0:Disable)", + 0, G_MAXINT32, 0, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_FORCE_IDR, + g_param_spec_boolean ("force-idr", "force-idr", "force next frame to be IDR", + FALSE, G_PARAM_WRITABLE)); + g_object_class_install_property (gobject_class, ARG_ENCODING_PRESET, + g_param_spec_enum ("encodingPreset", "Specifies which encoding preset to use", + "Specifies which encoding preset to use", + GST_TYPE_OMX_VIDEO_ENCODE_PRESETTYPE, + DEFAULT_ENCODE_PRESET, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_RATECONTROL_PRESET, + g_param_spec_enum ("rateControlPreset", "Specifies what rate control preset to use", + "Specifies what rate control preset to use", + GST_TYPE_OMX_VIDEO_RATECONTROL_PRESETTYPE, + DEFAULT_RATECONTROL_PRESET, + G_PARAM_READWRITE)); + + } +} + +static void +omx_h264_push_cb (GstOmxBaseFilter *omx_base, GstBuffer *buf) +{ + GstOmxH264Enc *self; + self = GST_OMX_H264ENC (omx_base); + /* Currently we use this logic to handle IDR period since the latest + * EZSDK version doesn't have support for OMX_IndexConfigVideoAVCIntraPeriod + */ + if ((self->idr_period > 0) || (self->force_idr)) + { + if ((self->cont == self->idr_period) || (self->force_idr)) + { + OMX_CONFIG_INTRAREFRESHVOPTYPE confIntraRefreshVOP; + + _G_OMX_INIT_PARAM (&confIntraRefreshVOP); + confIntraRefreshVOP.nPortIndex = omx_base->out_port->port_index; + + OMX_GetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoIntraVOPRefresh, + &confIntraRefreshVOP); + confIntraRefreshVOP.IntraRefreshVOP = TRUE; + + OMX_SetConfig (g_omx_core_get_handle (omx_base->gomx), + OMX_IndexConfigVideoIntraVOPRefresh, + &confIntraRefreshVOP); + + if (self->cont == self->idr_period) + self->cont = 0; + + if (self->force_idr) + { + self->force_idr = FALSE; + self->cont++; + } + } else { + self->cont++; + } } + GST_BUFFER_CAPS(buf) = gst_caps_ref(GST_PAD_CAPS(omx_base->srcpad)); } static void @@ -313,7 +611,9 @@ omx_setup (GstOmxBaseFilter *omx_base) { GstOmxBaseVideoEnc *self; GOmxCore *gomx; + GstOmxH264Enc *h264enc; + h264enc = GST_OMX_H264ENC (omx_base); self = GST_OMX_BASE_VIDEOENC (omx_base); gomx = (GOmxCore *) omx_base->gomx; @@ -325,9 +625,7 @@ omx_setup (GstOmxBaseFilter *omx_base) if (OMX_GetExtensionIndex (gomx->omx_handle, "OMX.TI.VideoEncode.Config.NALFormat", &index) == OMX_ErrorNone) { OMX_U32 nal_format; - GstOmxH264Enc *h264enc; - h264enc = GST_OMX_H264ENC (omx_base); nal_format = h264enc->bytestream ? 0 : 1; GST_DEBUG_OBJECT (omx_base, "setting 'OMX.TI.VideoEncode.Config.NALFormat' to %ld", nal_format); @@ -339,6 +637,36 @@ omx_setup (GstOmxBaseFilter *omx_base) } } + { + OMX_VIDEO_PARAM_AVCTYPE tAVCParams; + + _G_OMX_INIT_PARAM (&tAVCParams); + + tAVCParams.nPortIndex = OMX_DirOutput; + OMX_GetParameter(gomx->omx_handle, OMX_IndexParamVideoAvc, &tAVCParams); + + tAVCParams.eLevel = h264enc->level; + tAVCParams.eProfile = h264enc->profile; + tAVCParams.nPFrames = h264enc->i_period - 1; + tAVCParams.nBFrames = 0; + + OMX_SetParameter(gomx->omx_handle, OMX_IndexParamVideoAvc, &tAVCParams); + } + + { + OMX_VIDEO_PARAM_ENCODER_PRESETTYPE tEncoderPreset; + + _G_OMX_INIT_PARAM(&tEncoderPreset); + tEncoderPreset.nPortIndex = omx_base->out_port->port_index; + + OMX_GetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, &tEncoderPreset); + + tEncoderPreset.eEncodingModePreset = h264enc->encodingPreset; + tEncoderPreset.eRateControlPreset = h264enc->ratecontrolPreset; + + OMX_SetParameter(gomx->omx_handle, OMX_TI_IndexParamVideoEncoderPreset, &tEncoderPreset); + } + GST_INFO_OBJECT (omx_base, "end"); } @@ -371,6 +699,8 @@ settings_changed_cb (GOmxCore *core) "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, omx_base->framerate_num, omx_base->framerate_denom, + "stream-format", G_TYPE_STRING, "byte-stream", + "alignment", G_TYPE_STRING, "au", NULL); GST_INFO_OBJECT (omx_base, "caps are: %" GST_PTR_FORMAT, new_caps); @@ -384,13 +714,29 @@ type_instance_init (GTypeInstance *instance, { GstOmxBaseFilter *omx_base_filter; GstOmxBaseVideoEnc *omx_base; + GstOmxBaseFilterClass *bclass; + GstOmxH264Enc *self; omx_base_filter = GST_OMX_BASE_FILTER (instance); omx_base = GST_OMX_BASE_VIDEOENC (instance); + self = GST_OMX_H264ENC (instance); + bclass = GST_OMX_BASE_FILTER_CLASS (g_class); omx_base->omx_setup = omx_setup; + omx_base_filter->push_cb = omx_h264_push_cb; + omx_base->compression_format = OMX_VIDEO_CodingAVC; omx_base_filter->gomx->settings_changed_cb = settings_changed_cb; + + self->idr_period = 0; + self->cont = 0; + self->force_idr = FALSE; + + self->i_period = 90; + self->profile = DEFAULT_PROFILE; + self->level = DEFAULT_LEVEL; + self->encodingPreset = OMX_Video_Enc_High_Speed_Med_Quality; + self->ratecontrolPreset = OMX_Video_RC_Low_Delay; } diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.h index 9066092..a1966c0 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_h264enc.h @@ -38,6 +38,14 @@ struct GstOmxH264Enc { GstOmxBaseVideoEnc omx_base; gboolean bytestream; + gint idr_period; + gint force_idr; + OMX_VIDEO_AVCPROFILETYPE profile; + OMX_VIDEO_AVCLEVELTYPE level; + gint i_period; + OMX_VIDEO_ENCODING_MODE_PRESETTYPE encodingPreset; + OMX_VIDEO_RATECONTROL_PRESETTYPE ratecontrolPreset; + gint cont; }; struct GstOmxH264EncClass diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mjpegdec.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mjpegdec.c new file mode 100755 index 0000000..0e3cf6c --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mjpegdec.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2007-2009 Nokia Corporation. + * + * Author: Felipe Contreras <felipe.contreras@nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "gstomx_mjpegdec.h" +#include "gstomx.h" + +GSTOMX_BOILERPLATE (GstOmxMJPEGDec, gst_omx_mjpegdec, GstOmxBaseVideoDec, GST_OMX_BASE_VIDEODEC_TYPE); + +static GstCaps * +generate_sink_template (void) +{ + GstCaps *caps; + GstStructure *struc; + + caps = gst_caps_new_empty (); + +/* +image/jpeg +format: { I420, Y41B, UYVY, YV12 } +width: [ 0, 2147483647 ] +height: [ 0, 2147483647 ] +interlaced: { true, false } +framerate: [ 0/1, 2147483647/1 ] +parsed: true +*/ + struc = gst_structure_new ("image/jpeg", + "width", GST_TYPE_INT_RANGE, 16, 4096, + "height", GST_TYPE_INT_RANGE, 16, 4096, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, + NULL); + + gst_caps_append_structure (caps, struc); + + return caps; +} + +static void +type_base_init (gpointer g_class) +{ + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (g_class); + + { + GstElementDetails details; + + details.longname = "OpenMAX IL JPEG/MJPEG decoder"; + details.klass = "Codec/Decoder/Video"; + details.description = "Decodes video/images in MJPEG/JPEG format with OpenMAX IL"; + details.author = "Felipe Contreras"; + + gst_element_class_set_details (element_class, &details); + } + + { + GstPadTemplate *template; + + template = gst_pad_template_new ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, + generate_sink_template ()); + + gst_element_class_add_pad_template (element_class, template); + } +} + +static void +type_class_init (gpointer g_class, + gpointer class_data) +{ +} + +static void +initialize_port (GstOmxBaseFilter *omx_base) +{ + GstOmxBaseVideoDec *self; + GOmxCore *gomx; + OMX_PARAM_PORTDEFINITIONTYPE paramPort; + gint width, height; + GOmxPort *port; + + self = GST_OMX_BASE_VIDEODEC (omx_base); + gomx = (GOmxCore *) omx_base->gomx; + + GST_INFO_OBJECT (omx_base, "begin"); + + GST_DEBUG_OBJECT (self, "G_OMX_PORT_GET_DEFINITION (output)"); + G_OMX_PORT_GET_DEFINITION (omx_base->out_port, ¶mPort); + + width = self->extendedParams.width; + height = self->extendedParams.height; + + paramPort.nPortIndex = 1; + paramPort.nBufferCountActual = 20;//15;//output_buffer_count + paramPort.format.video.nFrameWidth = width; + paramPort.format.video.nFrameHeight = height; + paramPort.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused; + paramPort.format.video.eColorFormat = OMX_COLOR_FormatYUV420SemiPlanar; + paramPort.format.video.xFramerate = (60) << 16; + + GST_DEBUG_OBJECT (self, "nFrameWidth = %ld, nFrameHeight = %ld, nBufferCountActual = %ld", + paramPort.format.video.nFrameWidth, paramPort.format.video.nFrameHeight, + paramPort.nBufferCountActual); + + GST_DEBUG_OBJECT (self, "G_OMX_PORT_SET_DEFINITION (output)"); + G_OMX_PORT_SET_DEFINITION (omx_base->out_port, ¶mPort); + + G_OMX_PORT_GET_DEFINITION (omx_base->in_port, ¶mPort); + //paramPort.nBufferCountActual = 8; + paramPort.format.video.xFramerate = (60) << 16; + G_OMX_PORT_SET_DEFINITION (omx_base->in_port, ¶mPort); +#if 1 + port = g_omx_core_get_port (gomx, "input", 0); + + GST_DEBUG_OBJECT(self, "SendCommand(PortEnable, %d)", port->port_index); + OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, port->port_index, NULL); + g_sem_down (port->core->port_sem); + + port = g_omx_core_get_port (gomx, "output", 1); + + GST_DEBUG_OBJECT(self, "SendCommand(PortEnable, %d)", port->port_index); + OMX_SendCommand (g_omx_core_get_handle (port->core), + OMX_CommandPortEnable, port->port_index, NULL); + g_sem_down (port->core->port_sem); +#endif + GST_INFO_OBJECT (omx_base, "end"); +} + +static void +type_instance_init (GTypeInstance *instance, + gpointer g_class) +{ + GstOmxBaseVideoDec *omx_base; + + omx_base = GST_OMX_BASE_VIDEODEC (instance); + + omx_base->compression_format = OMX_VIDEO_CodingMJPEG; + omx_base->initialize_port = initialize_port; +} diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mjpegdec.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mjpegdec.h new file mode 100644 index 0000000..63a99b7 --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mjpegdec.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007-2009 Nokia Corporation. + * + * Author: Felipe Contreras <felipe.contreras@nokia.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef GSTOMX_MJPEGDEC_H +#define GSTOMX_MJPEGDEC_H + +#include <gst/gst.h> + +G_BEGIN_DECLS + +#define GST_OMX_MJPEGDEC(obj) (GstOmxMJPEGDec *) (obj) +#define GST_OMX_MJPEGDEC_TYPE (gst_omx_mjpegdec_get_type ()) + +typedef struct GstOmxMJPEGDec GstOmxMJPEGDec; +typedef struct GstOmxMJPEGDecClass GstOmxMJPEGDecClass; + +#include "gstomx_base_videodec.h" + +struct GstOmxMJPEGDec +{ + GstOmxBaseVideoDec omx_base; +}; + +struct GstOmxMJPEGDecClass +{ + GstOmxBaseVideoDecClass parent_class; +}; + +GType gst_omx_mjpegdec_get_type (void); + +G_END_DECLS + +#endif /* GSTOMX_MJPEGDEC_H */ diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mpeg2dec.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mpeg2dec.c index 15c5071..8e6c35c 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mpeg2dec.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_mpeg2dec.c @@ -232,7 +232,7 @@ initialize_port (GstOmxBaseFilter *omx_base) pOutPortDef.nBufferAlignment = 0x0; /* OMX_VIDEO_PORTDEFINITION values for output port */ - pOutPortDef.format.video.cMIMEType = "H264"; + pOutPortDef.format.video.cMIMEType = "MPEG2"; pOutPortDef.format.video.pNativeRender = NULL; pOutPortDef.format.video.nFrameWidth = width; pOutPortDef.format.video.nFrameHeight = height; diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.c index 47aa8e2..f4c04b5 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.c @@ -69,6 +69,7 @@ g_omx_port_new (GOmxCore *core, const gchar *name, guint index) port->enabled = TRUE; port->queue = async_queue_new (); port->mutex = g_mutex_new (); + port->cond = g_cond_new(); port->ignore_count = 0; port->n_offset = 0; @@ -83,6 +84,7 @@ g_omx_port_free (GOmxPort *port) DEBUG (port, "begin"); g_mutex_free (port->mutex); + g_cond_free(port->cond); async_queue_free (port->queue); g_free (port->name); @@ -240,7 +242,7 @@ g_omx_port_allocate_buffers (GOmxPort *port) if (!port->always_copy) { - buffer_data = port->share_buffer_info->pBuffer[i]; + buffer_data = port->share_buffer_info->pBuffer[i]; } else if (! port->share_buffer) { @@ -333,7 +335,7 @@ g_omx_port_start_buffers (GOmxPort *port) * the queue, otherwise send to omx for processing (fill it up). */ if (port->type == GOMX_PORT_INPUT) { - if (port->always_copy) + /*if (port->always_copy)*/ g_omx_core_got_buffer (port->core, port, omx_buffer); } else @@ -355,11 +357,14 @@ g_omx_port_push_buffer (GOmxPort *port, /* Avoid a race condition of pAppPrivate getting set to null after the buffer is submitted back again */ OMX_PTR appPrivate = omx_buffer->pAppPrivate; - omx_buffer->pAppPrivate = NULL; - gst_buffer_unref (appPrivate); - } - - async_queue_push (port->queue, omx_buffer); + //omx_buffer->pAppPrivate = NULL; + g_mutex_lock(port->mutex); + GST_BUFFER_FLAG_UNSET(appPrivate,GST_BUFFER_FLAG_BUSY); + gst_buffer_unref (appPrivate); + g_cond_signal(port->cond); + g_mutex_unlock(port->mutex); + } else + async_queue_push (port->queue, omx_buffer); } static gint @@ -724,7 +729,7 @@ send_prep_eos_event (GOmxPort *port, OMX_BUFFERHEADERTYPE *omx_buffer, GstEvent static OMX_BUFFERHEADERTYPE * get_input_buffer_header (GOmxPort *port, GstBuffer *src) { - OMX_BUFFERHEADERTYPE *omx_buffer; + OMX_BUFFERHEADERTYPE *omx_buffer,*tmp; int index; index = omxbuffer_index(port, GST_BUFFER_DATA (src)); @@ -732,7 +737,11 @@ get_input_buffer_header (GOmxPort *port, GstBuffer *src) omx_buffer = port->buffers[index]; omx_buffer->pBuffer = GST_BUFFER_DATA(src); - omx_buffer->nOffset = GST_GET_OMXBUFFER(src)->nOffset; + tmp = GST_GET_OMXBUFFER(src); + if(tmp) + omx_buffer->nOffset = tmp->nOffset; + else + omx_buffer->nOffset = 0; omx_buffer->nFilledLen = GST_BUFFER_SIZE (src); omx_buffer->pAppPrivate = gst_buffer_ref (src); @@ -740,6 +749,60 @@ get_input_buffer_header (GOmxPort *port, GstBuffer *src) } /** + * Sends a buffer to the OMX component 2-fields separately + */ +gint g_omx_port_send_interlaced_fields(GOmxPort *port, GstBuffer *buf, gint second_field_offset) +{ + OMX_BUFFERHEADERTYPE *out1, *out2, *in, *first, *second; + gint ret; + OMX_U8 *pBuffer; + int index; + + if (G_UNLIKELY((!GST_IS_OMXBUFFERTRANSPORT (buf)) || port->always_copy)) { + GST_ERROR_OBJECT(port->core->object,"Unexpected !!\n"); + return -1; /* something went wrong */ + } + + in = GST_GET_OMXBUFFER(buf); + + pBuffer = GST_BUFFER_DATA(buf); + index = omxbuffer_index(port, pBuffer); + out1 = port->buffers[index]; + index = omxbuffer_index(port, pBuffer + second_field_offset); + out2 = port->buffers[index]; + + out1->pBuffer = pBuffer; + out2->pBuffer = out1->pBuffer + second_field_offset; + out1->nOffset = out2->nOffset = in->nOffset; + out1->nFlags = OMX_TI_BUFFERFLAG_VIDEO_FRAME_TYPE_INTERLACE; + out2->nFlags = out1->nFlags | OMX_TI_BUFFERFLAG_VIDEO_FRAME_TYPE_INTERLACE_BOTTOM; + ret = out1->nFilledLen = in->nFilledLen; + out2->nFilledLen = (((in->nFilledLen + in->nOffset) *3) >> 2) - in->nOffset; + out1->pAppPrivate = gst_buffer_ref(buf); + out2->pAppPrivate = gst_buffer_ref(buf); + + if (in->nFlags & OMX_TI_BUFFERFLAG_VIDEO_FRAME_TYPE_INTERLACE_TOP_FIRST) { + first = out1; second = out2; } + else { first = out2; second = out1; } + + if (port->core->use_timestamps) { + if (GST_CLOCK_TIME_NONE != GST_BUFFER_TIMESTAMP (buf)) { + first->nTimeStamp = gst_util_uint64_scale_int ( + GST_BUFFER_TIMESTAMP (buf), + OMX_TICKS_PER_SECOND, GST_SECOND); + } else { + first->nTimeStamp = (OMX_TICKS)-1; + } + } + // Timestamp for the second field comes from adding duration to the + // First field timestamp + second->nTimeStamp = (OMX_TICKS)-1; + release_buffer (port, first); + release_buffer (port, second); + return ret; +} + +/** * Send a buffer/event to the OMX component. This handles conversion of * GST buffer, codec-data, and EOS events to the equivalent OMX buffer. * @@ -750,103 +813,102 @@ get_input_buffer_header (GOmxPort *port, GstBuffer *src) gint g_omx_port_send (GOmxPort *port, gpointer obj) { - - SendPrep send_prep = NULL; - - g_return_val_if_fail (port->type == GOMX_PORT_INPUT, -1); + SendPrep send_prep = NULL; - GstOmxBaseVideoDec *self = GST_OMX_BASE_VIDEODEC (port->core->object);; - - if (GST_IS_BUFFER (obj)) - { - if(self->compression_format == OMX_VIDEO_CodingWMV) - { - - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) - send_prep = (SendPrep)send_prep_wmv_codec_data; - else - send_prep = (SendPrep)send_prep_wmv_buffer_data; - } + g_return_val_if_fail (port->type == GOMX_PORT_INPUT, -1); + + + GstOmxBaseVideoDec *self = GST_OMX_BASE_VIDEODEC (port->core->object);; + + if (GST_IS_BUFFER (obj)) + { + if(self->compression_format == OMX_VIDEO_CodingWMV) + { + + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) + send_prep = (SendPrep)send_prep_wmv_codec_data; + else + send_prep = (SendPrep)send_prep_wmv_buffer_data; + } else if(self->compression_format == OMX_VIDEO_CodingMPEG4) + { + + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) + send_prep = (SendPrep)send_prep_wmv_codec_data; + else + send_prep = (SendPrep)send_prep_mpeg4_buffer_data; + } + else + { + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) + send_prep = (SendPrep)send_prep_codec_data; + else + send_prep = (SendPrep)send_prep_buffer_data; + } + } + else if (GST_IS_EVENT (obj)) { - - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) - send_prep = (SendPrep)send_prep_wmv_codec_data; - else - send_prep = (SendPrep)send_prep_mpeg4_buffer_data; + if (G_LIKELY (GST_EVENT_TYPE (obj) == GST_EVENT_EOS)) + send_prep = (SendPrep)send_prep_eos_event; } - else - { - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (obj, GST_BUFFER_FLAG_IN_CAPS))) - send_prep = (SendPrep)send_prep_codec_data; - else - send_prep = (SendPrep)send_prep_buffer_data; - } - } - else if (GST_IS_EVENT (obj)) - { - if (G_LIKELY (GST_EVENT_TYPE (obj) == GST_EVENT_EOS)) - send_prep = (SendPrep)send_prep_eos_event; - } - if (G_LIKELY (send_prep)) - { - gint ret; - OMX_BUFFERHEADERTYPE *omx_buffer = NULL; + if (G_LIKELY (send_prep)) + { + gint ret; + OMX_BUFFERHEADERTYPE *omx_buffer = NULL; - if (port->always_copy) - { - - omx_buffer = request_buffer (port); - if (!omx_buffer) - { - DEBUG (port, "null buffer"); - return -1; - } + if (port->always_copy) + { - /* don't assume OMX component clears flags! - */ - omx_buffer->nFlags = 0; + omx_buffer = request_buffer (port); + if (!omx_buffer) + { + DEBUG (port, "null buffer"); + return -1; + } - /* if buffer sharing is enabled, pAppPrivate might hold the ref to - * a buffer that is no longer required and should be unref'd. We - * do this check here, rather than in send_prep_buffer_data() so - * we don't keep the reference live in case, for example, this time - * the buffer is used for an EOS event. - */ - if (omx_buffer->pAppPrivate) - { - GstBuffer *old_buf = omx_buffer->pAppPrivate; - gst_buffer_unref (old_buf); - omx_buffer->pAppPrivate = NULL; - omx_buffer->pBuffer = NULL; /* just to ease debugging */ - } - } - else - { - - if (GST_IS_OMXBUFFERTRANSPORT (obj)) - omx_buffer = get_input_buffer_header (port, obj); - else if(GST_IS_EVENT (obj) && (GST_EVENT_TYPE (obj) == GST_EVENT_EOS)) { - omx_buffer = port->buffers[0]; - } - else { - GST_ERROR_OBJECT(port->core->object,"something went wrong!!\n"); - return -1; /* something went wrong */ - } - } + /* don't assume OMX component clears flags! + */ + omx_buffer->nFlags = 0; + + /* if buffer sharing is enabled, pAppPrivate might hold the ref to + * a buffer that is no longer required and should be unref'd. We + * do this check here, rather than in send_prep_buffer_data() so + * we don't keep the reference live in case, for example, this time + * the buffer is used for an EOS event. + */ + if (omx_buffer->pAppPrivate) + { + GstBuffer *old_buf = omx_buffer->pAppPrivate; + gst_buffer_unref (old_buf); + omx_buffer->pAppPrivate = NULL; + omx_buffer->pBuffer = NULL; /* just to ease debugging */ + } + } + else + { + if (GST_IS_OMXBUFFERTRANSPORT (obj)) + omx_buffer = get_input_buffer_header (port, obj); + else if(GST_IS_EVENT (obj) && (GST_EVENT_TYPE (obj) == GST_EVENT_EOS)) { + omx_buffer = port->buffers[0]; + } + else { + GST_ERROR_OBJECT(port->core->object,"something went wrong!!\n"); + return -1; /* something went wrong */ + } + } - send_prep (port, omx_buffer, obj); + send_prep (port, omx_buffer, obj); - ret = omx_buffer->nFilledLen; - release_buffer (port, omx_buffer); - return ret; - } - - WARNING (port, "unknown obj type"); - return -1; + ret = omx_buffer->nFilledLen; + release_buffer (port, omx_buffer); + return ret; + } + + WARNING (port, "unknown obj type"); + return -1; } /** @@ -999,7 +1061,7 @@ g_omx_port_recv (GOmxPort *port) #endif { setup_shared_buffer (port, omx_buffer); - if (port->always_copy) + if ((NULL == ret) || port->always_copy) release_buffer (port, omx_buffer); } } @@ -1037,7 +1099,7 @@ g_omx_port_flush (GOmxPort *port) { omx_buffer->nFilledLen = 0; -#ifdef USE_OMXTICORE +#if 0 if (omx_buffer->nFlags & OMX_TI_BUFFERFLAG_READONLY) { /* For output buffer that is marked with READONLY, we diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.h index e1ad8a9..563c70d 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_port.h @@ -30,6 +30,8 @@ G_BEGIN_DECLS +#define GST_BUFFER_FLAG_BUSY (GST_BUFFER_FLAG_LAST << 1) + /* Typedefs. */ typedef enum GOmxPortType GOmxPortType; @@ -88,6 +90,8 @@ struct GOmxPort /** if omx_allocate flag is not set then structure will contain upstream omx buffer pointer information */ OmxBufferInfo *share_buffer_info; + + GCond *cond; }; /* Macros. */ @@ -138,6 +142,7 @@ void g_omx_port_finish (GOmxPort *port); void g_omx_port_push_buffer (GOmxPort *port, OMX_BUFFERHEADERTYPE *omx_buffer); gint g_omx_port_send (GOmxPort *port, gpointer obj); gpointer g_omx_port_recv (GOmxPort *port); +gint g_omx_port_send_interlaced_fields(GOmxPort *port, GstBuffer *buf, gint second_field_offset); /* * Some domain specific port related utility functions: diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_scaler.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_scaler.c index 33e3cff..67488e2 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_scaler.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_scaler.c @@ -75,7 +75,7 @@ create_src_caps (GstOmxBaseFilter *omx_base) self = GST_OMX_BASE_VFPC (omx_base); caps = gst_pad_peer_get_caps (omx_base->srcpad); - if (gst_caps_is_empty (caps)) + if (NULL == caps || gst_caps_is_empty (caps)) { width = self->in_width; height = self->in_height; @@ -93,6 +93,8 @@ create_src_caps (GstOmxBaseFilter *omx_base) height = self->in_height; } } + /* Workaround: Make width multiple of 16, otherwise, scaler crashes */ + width = (width+15) & 0xFFFFFFF0; caps = gst_caps_new_empty (); struc = gst_structure_new (("video/x-raw-yuv"), @@ -218,10 +220,10 @@ omx_setup (GstOmxBaseFilter *omx_base) chResolution.Frm1Width = 0; chResolution.Frm1Height = 0; chResolution.Frm1Pitch = 0; - chResolution.FrmStartX = 0;//self->left; - chResolution.FrmStartY = 0;//self->top; - chResolution.FrmCropWidth = 0;//self->in_width - self->left; - chResolution.FrmCropHeight = 0;//self->in_height - self->top; + chResolution.FrmStartX = 0; + chResolution.FrmStartY = 0; + chResolution.FrmCropWidth = 0; + chResolution.FrmCropHeight = 0; chResolution.eDir = OMX_DirInput; chResolution.nChId = 0; err = OMX_SetConfig (gomx->omx_handle, OMX_TI_IndexConfigVidChResolution, &chResolution); diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_util.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_util.h index 88dc0f1..453c407 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_util.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_util.h @@ -99,7 +99,7 @@ static void type_base_init (gpointer g_class); \ static void type_class_init (gpointer g_class, gpointer class_data); \ static void type_instance_init (GTypeInstance *instance, gpointer g_class); \ static parent_type ## Class *parent_class; \ -static void type_class_init_trampoline (gpointer g_class, gpointer class_data)\ +static void type_class_init_trampoline ## type (gpointer g_class, gpointer class_data)\ { \ parent_class = g_type_class_ref (parent_type_macro); \ type_class_init (g_class, class_data); \ @@ -116,7 +116,7 @@ GType type_as_function ## _get_type (void) \ type_info = g_new0 (GTypeInfo, 1); \ type_info->class_size = sizeof (type ## Class); \ type_info->base_init = type_base_init; \ - type_info->class_init = type_class_init_trampoline; \ + type_info->class_init = type_class_init_trampoline ## type; \ type_info->instance_size = sizeof (type); \ type_info->instance_init = type_instance_init; \ _type = g_type_register_static (parent_type_macro, #type, type_info, 0);\ diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.c index 023a428..8fbab64 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.c @@ -34,6 +34,7 @@ enum ARG_NUM_INPUT_BUFFERS, ARG_NUM_OUTPUT_BUFFERS, ARG_PORT_INDEX, + ARG_FRAME_RATE }; static void init_interfaces (GType type); @@ -191,10 +192,12 @@ change_state (GstElement *element, g_omx_port_finish (self->in_port[ii]); g_omx_port_finish (self->out_port[ii]); } + //printf("setting EOS to true\n"); + self->eos = TRUE; for(ii = 0; ii < NUM_PORTS; ii++) async_queue_disable (self->chInfo[ii].queue); - - // printf("Waiting for ip thread to exit!!\n"); + //printf("Waiting for ip thread to exit..semup!!\n"); + g_sem_up(self->bufferSem); pthread_join(self->input_loop, &thread_ret); for(ii = 0; ii < NUM_PORTS; ii++) @@ -303,6 +306,9 @@ set_property (GObject *obj, if (!self->port_configured) //gstomx_vfpc_set_port_index (obj, self->port_index); break; + case ARG_FRAME_RATE: + self->framerate_num = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -338,7 +344,7 @@ get_property (GObject *obj, { OMX_PARAM_PORTDEFINITIONTYPE param; GOmxPort *port = (prop_id == ARG_NUM_INPUT_BUFFERS) ? - self->in_port : self->out_port; + self->in_port[0] : self->out_port[0]; G_OMX_PORT_GET_DEFINITION (port, ¶m); @@ -440,6 +446,11 @@ type_class_init (gpointer g_class, g_param_spec_uint ("port-index", "port index", "input/output start port index", 0, 8, 0, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, ARG_FRAME_RATE, + g_param_spec_uint ("framerate", "Frame Rate", + "The rate at which the mixer ocmponent would operate", + 1, 60, 15, G_PARAM_WRITABLE)); } } @@ -721,7 +732,7 @@ vidmix_port_recv (GstOmxVideoMixer *self) omx_bufferHdr[ii-1] = NULL; continue; } - //printf("Request buffer:%d!!\n",ii); + // printf("Request buffer:%d!!\n",ii); omx_buffer1 = request_buffer (port); //printf("got buffer:%d!!\n",ii); @@ -755,13 +766,16 @@ vidmix_port_recv (GstOmxVideoMixer *self) GST_BUFFER_SIZE(buf) = GST_BUFFER_SIZE(buf)*2; if (port->core->use_timestamps) { - GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int ( + /*GST_BUFFER_TIMESTAMP (buf) = gst_util_uint64_scale_int ( omx_buffer->nTimeStamp, - GST_SECOND, OMX_TICKS_PER_SECOND); + GST_SECOND, OMX_TICKS_PER_SECOND);*/ + GST_BUFFER_TIMESTAMP (buf) = self->timestamp; + GST_BUFFER_DURATION (buf) = self->duration; + self->timestamp += self->duration; } gst_omxbuffertransport_set_additional_headers (buf ,NUM_PORTS -1,&omx_bufferHdr); - + gst_omxbuffertransport_set_bufsem (buf ,self->bufferSem); port->n_offset = omx_buffer->nOffset; ret = buf; @@ -810,6 +824,10 @@ output_loop (gpointer data) { GstBuffer *buf = GST_BUFFER (obj); + /*printf("push : %" + GST_TIME_FORMAT ", duration: %" GST_TIME_FORMAT"\n", + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP(buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION(buf)));*/ ret = bclass->push_buffer (self, buf); GST_DEBUG_OBJECT (self, "ret=%s", gst_flow_get_name (ret)); @@ -986,7 +1004,7 @@ vidmix_port_allocate_buffers (GstOmxVideoMixer *self) size = param.nBufferSize; port->buffers = g_new0 (OMX_BUFFERHEADERTYPE *, port->num_buffers); - + printf("Input num bufffers:%d\n",port->num_buffers); for (i = 0; i < port->num_buffers; i++) { gpointer buffer_data = NULL; @@ -1039,6 +1057,7 @@ vidmix_port_allocate_buffers (GstOmxVideoMixer *self) g_return_if_fail (port->buffers[i]); //printf("allocated buffer:%p\n",port->buffers[i]->pBuffer); } + self->bufferSem = g_sem_new_with_value(port->num_buffers); }else { G_OMX_PORT_GET_DEFINITION (port, ¶m); size = param.nBufferSize; @@ -1105,6 +1124,9 @@ static void* vidmix_input_loop(void *arg) { GOmxCore *gomx; int kk=0; gint sent; + struct timeval tv; + guint64 afttime; + guint64 beftime; port = self->in_port[0]; gomx = port->core; @@ -1122,9 +1144,9 @@ static void* vidmix_input_loop(void *arg) { scaler_setup(self); - //printf("calline prepare!!\n"); + printf("calline prepare!!\n"); videomixer_prepare (self,self->gomx); - //printf("calline prepare returned!!\n"); + printf("calline prepare returned!!\n"); if (gomx->omx_state == OMX_StateIdle) { @@ -1160,32 +1182,74 @@ static void* vidmix_input_loop(void *arg) { { printf("port not ennabled!!\n"); } - + //printf("Init done!!\n"); while(TRUE) { + OMX_BUFFERHEADERTYPE *omx_buffer; + //printf("sem cnt:%d\n",self->bufferSem->counter); + + /*gettimeofday(&tv, NULL); + beftime = (tv.tv_sec * 1000000 + tv.tv_usec);*/ + g_sem_down(self->bufferSem); + /*gettimeofday(&tv, NULL); + afttime = (tv.tv_sec * 1000000 + tv.tv_usec); + printf("Wait:%lld\n",(afttime-beftime));*/ for(ii = 0; ii < NUM_PORTS; ii++) { port = self->in_port[ii]; gomx = port->core; buf = NULL; //printf("pop queue:%d\n",ii); if(self->chInfo[ii].eos == FALSE) { - buf = (GstBuffer *)async_queue_pop_full(self->chInfo[ii].queue,TRUE,FALSE); + //printf("force is FALSE\n"); + buf = (GstBuffer *)async_queue_pop_full(self->chInfo[ii].queue,FALSE,FALSE); if(buf == NULL) { + + if(self->eos == TRUE) { + printf("goto leave!!\n"); + goto leave; + } + //printf("NULL buffer...ip exiting!!\n"); - goto leave; + //printf("reuse:%d, buffer:%p!!\n",ii,self->chInfo[ii].lastBuf); + //buf = gst_buffer_ref(self->chInfo[ii].lastBuf); + //omx_buffer = GST_GET_OMXBUFFER(self->chInfo[ii].lastBuf); + g_mutex_lock(port->mutex); + //printf("wait:%d,buffer:%p\n",ii,self->chInfo[ii].lastBuf); + while(GST_BUFFER_FLAG_IS_SET(self->chInfo[ii].lastBuf,GST_BUFFER_FLAG_BUSY)) + g_cond_wait(port->cond,port->mutex); + //printf("wait done:%d\n",ii); + g_mutex_unlock(port->mutex); + + buf = (self->chInfo[ii].lastBuf); + //goto leave; + }else { + if(self->chInfo[ii].lastBuf) { + //printf("unref buffer:%p, refcnt:%d!!\n",self->chInfo[ii].lastBuf,GST_MINI_OBJECT_CAST(self->chInfo[ii].lastBuf)->refcount); + gst_buffer_unref(self->chInfo[ii].lastBuf); + } + //self->chInfo[ii].lastBuf = gst_buffer_ref(buf); + self->chInfo[ii].lastBuf = buf; } + + /*omx_buffer = GST_GET_OMXBUFFER(buf); + omx_buffer->nFlags |= OMX_BUFFERFLAG_BUSY;*/ //printf("send: %d:%p!!\n",ii,buf); + GST_BUFFER_FLAG_SET(buf,GST_BUFFER_FLAG_BUSY); sent = g_omx_port_send (port, buf); - gst_buffer_unref (buf); + //gst_buffer_unref (buf); } - + //sched_yield(); } } leave: - //printf("leaving ip thread!!\n"); + printf("leaving ip thread!!\n"); + for(ii = 0; ii < NUM_PORTS; ii++) + if(self->chInfo[ii].lastBuf) + gst_buffer_unref(self->chInfo[ii].lastBuf); + return NULL; } @@ -1208,7 +1272,7 @@ pad_chain (GstPad *pad, return ret; } PRINT_BUFFER (self, buf); - //printf("ip for channel %d\n",ch_info->idx); + // printf("ip for channel %d\n",ch_info->idx); gomx = self->gomx; GST_LOG_OBJECT (self, "begin: size=%u, state=%d", GST_BUFFER_SIZE (buf), gomx->omx_state); @@ -1229,7 +1293,7 @@ pad_chain (GstPad *pad, leave: GST_LOG_OBJECT (self, "end"); - //printf("leaving!!\n"); + // printf("leaving :%d!!\n",ch_info->idx); return ret; /* special conditions */ @@ -1513,7 +1577,7 @@ sink_setcaps (GstPad *pad, { ch_info->in_stride = gstomx_calculate_stride (ch_info->in_width, format); } - +#if 0 { const GValue *framerate = NULL; framerate = gst_structure_get_value (structure, "framerate"); @@ -1522,13 +1586,15 @@ sink_setcaps (GstPad *pad, self->framerate_num = gst_value_get_fraction_numerator (framerate); self->framerate_denom = gst_value_get_fraction_denominator (framerate); - omx_base->duration = gst_util_uint64_scale_int(GST_SECOND, + /* omx_base->duration = gst_util_uint64_scale_int(GST_SECOND, gst_value_get_fraction_denominator (framerate), gst_value_get_fraction_numerator (framerate)); GST_DEBUG_OBJECT (self, "Nominal frame duration =%"GST_TIME_FORMAT, - GST_TIME_ARGS (omx_base->duration)); + GST_TIME_ARGS (omx_base->duration));*/ } } +#endif + self->duration = ((guint64)GST_SECOND/self->framerate_num); if (self->sink_setcaps) self->sink_setcaps (pad, caps); @@ -1630,6 +1696,7 @@ type_instance_init (GTypeInstance *instance, self->chInfo[ii].queue = async_queue_new (); self->chInfo[ii].idx = ii; self->chInfo[ii].eos = FALSE; + self->chInfo[ii].lastBuf = NULL; printf("queue_%d : %p\n",ii,self->chInfo[ii].queue); gst_pad_set_element_private(self->sinkpad[ii], &(self->chInfo[ii])); @@ -1650,9 +1717,13 @@ type_instance_init (GTypeInstance *instance, gst_pad_set_setcaps_function (self->srcpad, GST_DEBUG_FUNCPTR (src_setcaps)); - - self->duration = GST_CLOCK_TIME_NONE; - printf("In instance init/...done!!\n"); + + self->framerate_num = 15; + self->framerate_denom = 1; + self->timestamp = 0; + /*printf("duration:%lld, in time : %" + GST_TIME_FORMAT "\n",self->duration,GST_TIME_ARGS(self->duration)); + printf("In instance init/...done!!\n");*/ GST_LOG_OBJECT (self, "end"); } diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.h index 9255e08..7adf186 100755 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.h +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomx_videomixer.h @@ -49,6 +49,7 @@ typedef struct ip_params { gint in_width, in_height, in_stride; AsyncQueue *queue; gboolean eos; + GstBuffer *lastBuf; } ip_params ; @@ -88,9 +89,10 @@ struct GstOmxVideoMixer //gpointer g_class; ip_params chInfo[NUM_PORTS]; guint numEosPending; + GSem *bufferSem; + GstClockTime timestamp; }; - struct GstOmxVideoMixerClass { GstElementClass parent_class; diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomxbufferalloc.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomxbufferalloc.c new file mode 100755 index 0000000..e92fd9d --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomxbufferalloc.c @@ -0,0 +1,348 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org> + * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net> + * Copyright (C) 2011 prashant <<user@hostname.org>> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-omxbufferalloc + * + * FIXME:Describe omxbufferalloc here. + * + * <refsect2> + * <title>Example launch line</title> + * |[ + * gst-launch -v -m fakesrc ! omxbufferalloc ! fakesink silent=TRUE + * ]| + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gst/gst.h> +#include "gstomx.h" +#include "gstomx_interface.h" + +#include "gstomxbufferalloc.h" + + +GST_DEBUG_CATEGORY_STATIC (gst_omx_buffer_alloc_debug); +//#define GST_CAT_DEFAULT gst_omx_buffer_alloc_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_SILENT, + PROP_NUMBUFFERS +}; + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("ANY") + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("ANY") + ); + +GST_BOILERPLATE (GstomxBufferAlloc, gst_omx_buffer_alloc, GstElement, + GST_TYPE_ELEMENT); + +static void gst_omx_buffer_alloc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_omx_buffer_alloc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_omx_buffer_alloc_set_caps (GstPad * pad, GstCaps * caps); +static GstFlowReturn gst_omx_buffer_alloc_chain (GstPad * pad, GstBuffer * buf); + +GstFlowReturn +gst_omx_buffer_alloc_bufferalloc (GstPad *pad, guint64 offset, guint size, + GstCaps *caps, GstBuffer **buf); + +static GstStateChangeReturn +gst_omx_buffer_alloc_change_state (GstElement *element, + GstStateChange transition); + + + +/* GObject vmethod implementations */ + +static void +gst_omx_buffer_alloc_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple(element_class, + "omxBufferAlloc", + "FIXME:Generic", + "FIXME:Generic Template Element", + "prashant <<user@hostname.org>>"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +/* initialize the omxbufferalloc's class */ +static void +gst_omx_buffer_alloc_class_init (GstomxBufferAllocClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_omx_buffer_alloc_set_property; + gobject_class->get_property = gst_omx_buffer_alloc_get_property; + gstelement_class->change_state = gst_omx_buffer_alloc_change_state; + + g_object_class_install_property (gobject_class, PROP_NUMBUFFERS, + g_param_spec_uint ("numBuffers", "number of buffers", + "Number of buffers to be allocated by component", + 1, 16, 10, G_PARAM_WRITABLE)); + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE)); + +} + +/* initialize the new element + * instantiate pads and add them to element + * set pad calback functions + * initialize instance structure + */ +static void +gst_omx_buffer_alloc_init (GstomxBufferAlloc * filter, + GstomxBufferAllocClass * gclass) +{ + filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); + gst_pad_set_setcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR(gst_omx_buffer_alloc_set_caps)); + gst_pad_set_getcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps)); + gst_pad_set_chain_function (filter->sinkpad, + GST_DEBUG_FUNCPTR(gst_omx_buffer_alloc_chain)); + + gst_pad_set_bufferalloc_function(filter->sinkpad,GST_DEBUG_FUNCPTR(gst_omx_buffer_alloc_bufferalloc)); + + filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); + gst_pad_set_getcaps_function (filter->srcpad, + GST_DEBUG_FUNCPTR(gst_pad_proxy_getcaps)); + + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + filter->silent = FALSE; + filter->out_port.num_buffers = 10; + filter->out_port.always_copy = FALSE; + filter->cnt = 0; + filter->out_port.buffers = NULL; +} + +static void +gst_omx_buffer_alloc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstomxBufferAlloc *filter = GST_OMXBUFFERALLOC (object); + + switch (prop_id) { + case PROP_SILENT: + filter->silent = g_value_get_boolean (value); + break; + case PROP_NUMBUFFERS: + filter->out_port.num_buffers = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_omx_buffer_alloc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstomxBufferAlloc *filter = GST_OMXBUFFERALLOC (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, filter->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* GstElement vmethod implementations */ + +/* this function handles the link with other elements */ +static gboolean +gst_omx_buffer_alloc_set_caps (GstPad * pad, GstCaps * caps) +{ + GstomxBufferAlloc *filter; + GstPad *otherpad; + + filter = GST_OMXBUFFERALLOC (gst_pad_get_parent (pad)); + otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; + gst_object_unref (filter); + + return gst_pad_set_caps (otherpad, caps); +} + +/* chain function + * this function does the actual processing + */ +static GstFlowReturn +gst_omx_buffer_alloc_chain (GstPad * pad, GstBuffer * buf) +{ + GstomxBufferAlloc *filter; + + filter = GST_OMXBUFFERALLOC (GST_OBJECT_PARENT (pad)); + + buf = gst_omxbuffertransport_clone (buf, &(filter->out_port)); + + /* just push out the incoming buffer without touching it */ + return gst_pad_push (filter->srcpad, buf); +} + +void +gst_omx_buffer_alloc_allocate_buffers (GstomxBufferAlloc *filter, guint size) +{ + guint ii; + guint numBufs; + + numBufs = filter->out_port.num_buffers; + printf("allocating %d buffers of size:%d!!\n",numBufs,size); + filter->out_port.buffers = g_new0 (OMX_BUFFERHEADERTYPE *, numBufs); + filter->heap = SharedRegion_getHeap(2); + + for(ii = 0; ii < numBufs; ii++) { + filter->out_port.buffers[ii] = malloc(sizeof(OMX_BUFFERHEADERTYPE)); + filter->out_port.buffers[ii]->pBuffer = Memory_alloc (filter->heap, size, 128, NULL); + printf("allocated outbuf:%p\n",filter->out_port.buffers[ii]->pBuffer); + } + filter->allocSize = size; + + return; +} + +GstFlowReturn +gst_omx_buffer_alloc_bufferalloc (GstPad *pad, guint64 offset, guint size, + GstCaps *caps, GstBuffer **buf) +{ + GstomxBufferAlloc *filter; + filter = GST_OMXBUFFERALLOC (GST_OBJECT_PARENT (pad)); + if(filter->out_port.buffers == NULL) + gst_omx_buffer_alloc_allocate_buffers (filter,size); + + *buf = gst_buffer_new(); + GST_BUFFER_DATA(*buf) = filter->out_port.buffers[filter->cnt++]->pBuffer; + GST_BUFFER_SIZE(*buf) = size; + GST_BUFFER_CAPS(*buf) = caps; + return; +} + +static GstStateChangeReturn +gst_omx_buffer_alloc_change_state (GstElement *element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstomxBufferAlloc *filter = GST_OMXBUFFERALLOC (element); + guint ii; + switch (transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + OMX_Init (); + break; + + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + if (ret == GST_STATE_CHANGE_FAILURE) + goto leave; + + switch (transition) + { + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + for(ii = 0; ii < filter->out_port.num_buffers; ii++) { + Memory_free(filter->heap,filter->out_port.buffers[ii]->pBuffer,filter->allocSize); + } + g_free(filter->out_port.buffers); + OMX_Deinit(); + break; + + default: + break; + } + +leave: + return ret; +} + + + + diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomxbufferalloc.h b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomxbufferalloc.h new file mode 100755 index 0000000..fbd9573 --- /dev/null +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstomxbufferalloc.h @@ -0,0 +1,96 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org> + * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net> + * Copyright (C) 2011 prashant <<user@hostname.org>> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_OMXBUFFERALLOC_H__ +#define __GST_OMXBUFFERALLOC_H__ + +#include <gst/gst.h> +#include "gstomx_util.h" + +#include <xdc/std.h> +#include <ti/syslink/utils/IHeap.h> + + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_OMXBUFFERALLOC \ + (gst_omx_buffer_alloc_get_type()) +#define GST_OMXBUFFERALLOC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMXBUFFERALLOC,GstomxBufferAlloc)) +#define GST_OMXBUFFERALLOC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMXBUFFERALLOC,GstomxBufferAllocClass)) +#define GST_IS_OMXBUFFERALLOC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMXBUFFERALLOC)) +#define GST_IS_OMXBUFFERALLOC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMXBUFFERALLOC)) + +typedef struct _GstomxBufferAlloc GstomxBufferAlloc; +typedef struct _GstomxBufferAllocClass GstomxBufferAllocClass; + +struct _GstomxBufferAlloc +{ + GstElement element; + + GstPad *sinkpad, *srcpad; + + gboolean silent; + + GOmxPort out_port; + guint cnt; + IHeap_Handle heap; + guint allocSize; +}; + +struct _GstomxBufferAllocClass +{ + GstElementClass parent_class; +}; + +GType gst_omx_buffer_alloc_get_type (void); + +G_END_DECLS + +#endif /* __GST_OMXBUFFERALLOC_H__ */ diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstperf.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstperf.c index 5fb6084..13e77ca 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstperf.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/omx/gstperf.c @@ -83,6 +83,7 @@ display_current_fps (gpointer data) gchar fps_message[256]; gdouble time_diff, time_elapsed; GstClockTime current_ts = gst_util_get_timestamp (); + char *name = GST_OBJECT_NAME(self); frames_count = self->frames_count; @@ -93,8 +94,8 @@ display_current_fps (gpointer data) average_fps = (gdouble) frames_count / time_elapsed; - g_snprintf (fps_message, 255, "frames: %" G_GUINT64_FORMAT " \tcurrent: %.2f\t average: %.2f", - frames_count, rr, average_fps); + g_snprintf (fps_message, 255, "%s: frames: %" G_GUINT64_FORMAT " \tcurrent: %.2f\t average: %.2f", + name, frames_count, rr, average_fps); g_print ("%s", fps_message); self->last_frames_count = frames_count; diff --git a/gstreamer_ti_dm81xx/ti_build/gst-openmax/util/sem.c b/gstreamer_ti_dm81xx/ti_build/gst-openmax/util/sem.c index 2ac6fac..fac8282 100644 --- a/gstreamer_ti_dm81xx/ti_build/gst-openmax/util/sem.c +++ b/gstreamer_ti_dm81xx/ti_build/gst-openmax/util/sem.c @@ -36,6 +36,19 @@ g_sem_new (void) return sem; } +GSem * +g_sem_new_with_value (gint value) +{ + GSem *sem; + + sem = g_new (GSem, 1); + sem->condition = g_cond_new (); + sem->mutex = g_mutex_new (); + sem->counter = value; + + return sem; +} + void g_sem_free (GSem *sem) { |