summaryrefslogtreecommitdiff
path: root/omx/gstomxvideo.c
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2014-03-03 16:15:24 +0100
committerSebastian Dröge <sebastian@centricular.com>2014-03-12 12:47:09 +0100
commit6bf4d9a498ca163a0c431e8a864658922a8bab1f (patch)
treeffe60aa8862b777b6020dfefe63d95e140ceb8e2 /omx/gstomxvideo.c
parentc4426a49db961b99ead4845fe2dcb6adfe84381e (diff)
downloadgst-omx-6bf4d9a498ca163a0c431e8a864658922a8bab1f.tar.gz
omxvideo: start sharing more code between video decoder and encoder
Identical functionality spread of two different components. We can't use a common base class because of different inheritance, but let's try to share the code anyway. https://bugzilla.gnome.org/show_bug.cgi?id=726024
Diffstat (limited to 'omx/gstomxvideo.c')
-rw-r--r--omx/gstomxvideo.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/omx/gstomxvideo.c b/omx/gstomxvideo.c
new file mode 100644
index 0000000..c282fd2
--- /dev/null
+++ b/omx/gstomxvideo.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ * Author: Christian König <christian.koenig@amd.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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstomxvideo.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_omx_video_debug_category);
+#define GST_CAT_DEFAULT gst_omx_video_debug_category
+
+GList *
+gst_omx_video_get_supported_colorformats (GstOMXPort * port,
+ GstVideoCodecState * state)
+{
+ GstOMXComponent *comp = port->comp;
+ OMX_VIDEO_PARAM_PORTFORMATTYPE param;
+ OMX_ERRORTYPE err;
+ GList *negotiation_map = NULL;
+ gint old_index;
+ GstOMXVideoNegotiationMap *m;
+
+ GST_OMX_INIT_STRUCT (&param);
+ param.nPortIndex = port->index;
+ param.nIndex = 0;
+ if (!state || state->info.fps_n == 0)
+ param.xFramerate = 0;
+ else
+ param.xFramerate = (state->info.fps_n << 16) / (state->info.fps_d);
+
+ old_index = -1;
+ do {
+ err =
+ gst_omx_component_get_parameter (comp,
+ OMX_IndexParamVideoPortFormat, &param);
+
+ /* FIXME: Workaround for Bellagio that simply always
+ * returns the same value regardless of nIndex and
+ * never returns OMX_ErrorNoMore
+ */
+ if (old_index == param.nIndex)
+ break;
+
+ if (err == OMX_ErrorNone || err == OMX_ErrorNoMore) {
+ switch (param.eColorFormat) {
+ case OMX_COLOR_FormatYUV420Planar:
+ case OMX_COLOR_FormatYUV420PackedPlanar:
+ m = g_slice_new (GstOMXVideoNegotiationMap);
+ m->format = GST_VIDEO_FORMAT_I420;
+ m->type = param.eColorFormat;
+ negotiation_map = g_list_append (negotiation_map, m);
+ GST_DEBUG_OBJECT (comp->parent,
+ "Component supports I420 (%d) at index %u",
+ param.eColorFormat, (guint) param.nIndex);
+ break;
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ m = g_slice_new (GstOMXVideoNegotiationMap);
+ m->format = GST_VIDEO_FORMAT_NV12;
+ m->type = param.eColorFormat;
+ negotiation_map = g_list_append (negotiation_map, m);
+ GST_DEBUG_OBJECT (comp->parent,
+ "Component supports NV12 (%d) at index %u",
+ param.eColorFormat, (guint) param.nIndex);
+ break;
+ default:
+ GST_DEBUG_OBJECT (comp->parent,
+ "Component supports unsupported color format %d at index %u",
+ param.eColorFormat, (guint) param.nIndex);
+ break;
+ }
+ }
+ old_index = param.nIndex++;
+ } while (err == OMX_ErrorNone);
+
+ return negotiation_map;
+}
+
+GstCaps *
+gst_omx_video_get_caps_4_map (GList * map)
+{
+ GstCaps *caps = gst_caps_new_empty ();
+ GList *l;
+
+ for (l = map; l; l = l->next) {
+ GstOMXVideoNegotiationMap *entry = l->data;
+
+ gst_caps_append_structure (caps,
+ gst_structure_new ("video/x-raw",
+ "format", G_TYPE_STRING,
+ gst_video_format_to_string (entry->format), NULL));
+ }
+ return caps;
+}
+
+void
+gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m)
+{
+ g_slice_free (GstOMXVideoNegotiationMap, m);
+}
+
+GstVideoCodecFrame *
+gst_omx_video_find_nearest_frame (GstOMXBuffer * buf, GList * frames)
+{
+ GstVideoCodecFrame *best = NULL;
+ GstClockTimeDiff best_diff = G_MAXINT64;
+ GstClockTime timestamp;
+ GList *l;
+
+ timestamp =
+ gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
+ OMX_TICKS_PER_SECOND);
+
+ for (l = frames; l; l = l->next) {
+ GstVideoCodecFrame *tmp = l->data;
+ GstClockTimeDiff diff = ABS (GST_CLOCK_DIFF (timestamp, tmp->pts));
+
+ if (diff < best_diff) {
+ best = tmp;
+ best_diff = diff;
+
+ if (diff == 0)
+ break;
+ }
+ }
+
+ if (best)
+ gst_video_codec_frame_ref (best);
+
+ g_list_foreach (frames, (GFunc) gst_video_codec_frame_unref, NULL);
+ g_list_free (frames);
+
+ return best;
+}