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
libgstomx_la_SOURCES = \
gstomx.c \
gstomxbufferpool.c \
+ gstomxvideo.c \
gstomxvideodec.c \
gstomxvideoenc.c \
gstomxaudioenc.c \
noinst_HEADERS = \
gstomx.h \
+ gstomxvideo.h \
gstomxvideodec.h \
gstomxvideoenc.h \
gstomxaudioenc.h \
--- /dev/null
+/*
+ * 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 (¶m);
+ 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, ¶m);
+
+ /* 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;
+}
--- /dev/null
+/*
+ * 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
+ *
+ */
+
+#ifndef __GST_OMX_VIDEO_H__
+#define __GST_OMX_VIDEO_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+
+#include "gstomx.h"
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ GstVideoFormat format;
+ OMX_COLOR_FORMATTYPE type;
+} GstOMXVideoNegotiationMap;
+
+GList *
+gst_omx_video_get_supported_colorformats (GstOMXPort * port,
+ GstVideoCodecState * state);
+
+GstCaps * gst_omx_video_get_caps_4_map(GList * map);
+
+void
+gst_omx_video_negotiation_map_free (GstOMXVideoNegotiationMap * m);
+
+GstVideoCodecFrame *
+gst_omx_video_find_nearest_frame (GstOMXBuffer * buf, GList * frames);
+
+G_END_DECLS
+
+#endif /* __GST_OMX_VIDEO_H__ */
#include <string.h>
#include "gstomxbufferpool.h"
+#include "gstomxvideo.h"
#include "gstomxvideodec.h"
GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category);
return ret;
}
-static GstVideoCodecFrame *
-gst_omx_video_dec_find_nearest_frame (GstOMXVideoDec * self, GstOMXBuffer * buf)
-{
- GstVideoCodecFrame *best = NULL;
- GstClockTimeDiff best_diff = G_MAXINT64;
- GstClockTime timestamp;
- GList *frames;
- GList *l;
-
- timestamp =
- gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
- OMX_TICKS_PER_SECOND);
-
- frames = gst_video_decoder_get_frames (GST_VIDEO_DECODER (self));
-
- 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;
-}
-
static gboolean
gst_omx_video_dec_fill_buffer (GstOMXVideoDec * self,
GstOMXBuffer * inbuf, GstBuffer * outbuf)
(guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
GST_VIDEO_DECODER_STREAM_LOCK (self);
- frame = gst_omx_video_dec_find_nearest_frame (self, buf);
+ frame = gst_omx_video_find_nearest_frame (buf,
+ gst_video_decoder_get_frames (GST_VIDEO_DECODER (self)));
if (frame
&& (deadline = gst_video_decoder_get_max_decode_time
return TRUE;
}
-typedef struct
-{
- GstVideoFormat format;
- OMX_COLOR_FORMATTYPE type;
-} VideoNegotiationMap;
-
-static void
-video_negotiation_map_free (VideoNegotiationMap * m)
-{
- g_slice_free (VideoNegotiationMap, m);
-}
-
-static GList *
-gst_omx_video_dec_get_supported_colorformats (GstOMXVideoDec * self)
-{
- GstOMXComponent *comp;
- GstOMXPort *port;
- GstVideoCodecState *state = self->input_state;
- OMX_VIDEO_PARAM_PORTFORMATTYPE param;
- OMX_ERRORTYPE err;
- GList *negotiation_map = NULL;
- gint old_index;
- VideoNegotiationMap *m;
-
- port = self->dec_out_port;
- comp = self->dec;
-
- GST_OMX_INIT_STRUCT (¶m);
- 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, ¶m);
-
- /* 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 (VideoNegotiationMap);
- m->format = GST_VIDEO_FORMAT_I420;
- m->type = param.eColorFormat;
- negotiation_map = g_list_append (negotiation_map, m);
- GST_DEBUG_OBJECT (self, "Component supports I420 (%d) at index %u",
- param.eColorFormat, (guint) param.nIndex);
- break;
- case OMX_COLOR_FormatYUV420SemiPlanar:
- m = g_slice_new (VideoNegotiationMap);
- m->format = GST_VIDEO_FORMAT_NV12;
- m->type = param.eColorFormat;
- negotiation_map = g_list_append (negotiation_map, m);
- GST_DEBUG_OBJECT (self, "Component supports NV12 (%d) at index %u",
- param.eColorFormat, (guint) param.nIndex);
- break;
- default:
- GST_DEBUG_OBJECT (self,
- "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;
-}
-
static gboolean
gst_omx_video_dec_negotiate (GstOMXVideoDec * self)
{
GST_DEBUG_OBJECT (self, "Allowed downstream caps: %" GST_PTR_FORMAT,
intersection);
- negotiation_map = gst_omx_video_dec_get_supported_colorformats (self);
- comp_supported_caps = gst_caps_new_empty ();
- for (l = negotiation_map; l; l = l->next) {
- VideoNegotiationMap *map = l->data;
+ negotiation_map =
+ gst_omx_video_get_supported_colorformats (self->dec_out_port,
+ self->input_state);
- gst_caps_append_structure (comp_supported_caps,
- gst_structure_new ("video/x-raw",
- "format", G_TYPE_STRING,
- gst_video_format_to_string (map->format), NULL));
- }
+ comp_supported_caps = gst_omx_video_get_caps_4_map (negotiation_map);
if (!gst_caps_is_empty (comp_supported_caps)) {
GstCaps *tmp;
gst_caps_unref (intersection);
GST_ERROR_OBJECT (self, "Empty caps");
g_list_free_full (negotiation_map,
- (GDestroyNotify) video_negotiation_map_free);
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
return FALSE;
}
GST_ERROR_OBJECT (self, "Invalid caps: %" GST_PTR_FORMAT, intersection);
gst_caps_unref (intersection);
g_list_free_full (negotiation_map,
- (GDestroyNotify) video_negotiation_map_free);
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
return FALSE;
}
gst_caps_unref (intersection);
param.nPortIndex = self->dec_out_port->index;
for (l = negotiation_map; l; l = l->next) {
- VideoNegotiationMap *m = l->data;
+ GstOMXVideoNegotiationMap *m = l->data;
if (m->format == format) {
param.eColorFormat = m->type;
/* We must find something here */
g_assert (l != NULL);
g_list_free_full (negotiation_map,
- (GDestroyNotify) video_negotiation_map_free);
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
err =
gst_omx_component_set_parameter (self->dec,
#include <gst/video/gstvideometa.h>
#include <string.h>
+#include "gstomxvideo.h"
#include "gstomxvideoenc.h"
GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category);
return ret;
}
-static GstVideoCodecFrame *
-gst_omx_video_enc_find_nearest_frame (GstOMXVideoEnc * self, GstOMXBuffer * buf)
-{
- GstVideoCodecFrame *best = NULL;
- GstClockTimeDiff best_diff = G_MAXINT64;
- GstClockTime timestamp;
- GList *frames;
- GList *l;
-
- timestamp =
- gst_util_uint64_scale (buf->omx_buf->nTimeStamp, GST_SECOND,
- OMX_TICKS_PER_SECOND);
-
- frames = gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self));
-
- 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;
-}
-
static GstFlowReturn
gst_omx_video_enc_handle_output_frame (GstOMXVideoEnc * self, GstOMXPort * port,
GstOMXBuffer * buf, GstVideoCodecFrame * frame)
(guint) buf->omx_buf->nFlags, (guint64) buf->omx_buf->nTimeStamp);
GST_VIDEO_ENCODER_STREAM_LOCK (self);
- frame = gst_omx_video_enc_find_nearest_frame (self, buf);
+ frame = gst_omx_video_find_nearest_frame (buf,
+ gst_video_encoder_get_frames (GST_VIDEO_ENCODER (self)));
g_assert (klass->handle_output_frame);
flow_ret = klass->handle_output_frame (self, self->enc_out_port, buf, frame);
return TRUE;
}
-typedef struct
-{
- GstVideoFormat format;
- OMX_COLOR_FORMATTYPE type;
-} VideoNegotiationMap;
-
-static void
-video_negotiation_map_free (VideoNegotiationMap * m)
-{
- g_slice_free (VideoNegotiationMap, m);
-}
-
-static GList *
-gst_omx_video_enc_get_supported_colorformats (GstOMXVideoEnc * self)
-{
- GstOMXPort *port = self->enc_in_port;
- GstVideoCodecState *state = self->input_state;
- OMX_VIDEO_PARAM_PORTFORMATTYPE param;
- OMX_ERRORTYPE err;
- GList *negotiation_map = NULL;
- gint old_index;
-
- GST_OMX_INIT_STRUCT (¶m);
- 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 {
- VideoNegotiationMap *m;
-
- err =
- gst_omx_component_get_parameter (self->enc,
- OMX_IndexParamVideoPortFormat, ¶m);
-
- /* 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 (VideoNegotiationMap);
- m->format = GST_VIDEO_FORMAT_I420;
- m->type = param.eColorFormat;
- negotiation_map = g_list_append (negotiation_map, m);
- GST_DEBUG_OBJECT (self, "Component supports I420 (%d) at index %u",
- param.eColorFormat, (guint) param.nIndex);
- break;
- case OMX_COLOR_FormatYUV420SemiPlanar:
- m = g_slice_new (VideoNegotiationMap);
- m->format = GST_VIDEO_FORMAT_NV12;
- m->type = param.eColorFormat;
- negotiation_map = g_list_append (negotiation_map, m);
- GST_DEBUG_OBJECT (self, "Component supports NV12 (%d) at index %u",
- param.eColorFormat, (guint) param.nIndex);
- break;
- default:
- GST_DEBUG_OBJECT (self,
- "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;
-}
-
static gboolean
gst_omx_video_enc_set_format (GstVideoEncoder * encoder,
GstVideoCodecState * state)
GST_DEBUG_OBJECT (self, "Encoder drained and disabled");
}
- negotiation_map = gst_omx_video_enc_get_supported_colorformats (self);
+ negotiation_map =
+ gst_omx_video_get_supported_colorformats (self->enc_in_port,
+ self->input_state);
if (!negotiation_map) {
/* Fallback */
switch (info->finfo->format) {
}
} else {
for (l = negotiation_map; l; l = l->next) {
- VideoNegotiationMap *m = l->data;
+ GstOMXVideoNegotiationMap *m = l->data;
if (m->format == info->finfo->format) {
port_def.format.video.eColorFormat = m->type;
}
}
g_list_free_full (negotiation_map,
- (GDestroyNotify) video_negotiation_map_free);
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
}
port_def.format.video.nFrameWidth = info->width;
gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
{
GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
- GList *negotiation_map = NULL, *l;
+ GList *negotiation_map = NULL;
GstCaps *comp_supported_caps;
if (!self->enc)
return gst_video_encoder_proxy_getcaps (encoder, NULL, filter);
- negotiation_map = gst_omx_video_enc_get_supported_colorformats (self);
- comp_supported_caps = gst_caps_new_empty ();
- for (l = negotiation_map; l; l = l->next) {
- VideoNegotiationMap *map = l->data;
-
- gst_caps_append_structure (comp_supported_caps,
- gst_structure_new ("video/x-raw",
- "format", G_TYPE_STRING,
- gst_video_format_to_string (map->format), NULL));
- }
+ negotiation_map =
+ gst_omx_video_get_supported_colorformats (self->enc_in_port,
+ self->input_state);
+ comp_supported_caps = gst_omx_video_get_caps_4_map (negotiation_map);
g_list_free_full (negotiation_map,
- (GDestroyNotify) video_negotiation_map_free);
+ (GDestroyNotify) gst_omx_video_negotiation_map_free);
if (!gst_caps_is_empty (comp_supported_caps)) {
GstCaps *ret =