diff options
author | Christian König <christian.koenig@amd.com> | 2014-03-03 16:15:24 +0100 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2014-03-12 12:47:09 +0100 |
commit | 6bf4d9a498ca163a0c431e8a864658922a8bab1f (patch) | |
tree | ffe60aa8862b777b6020dfefe63d95e140ceb8e2 | |
parent | c4426a49db961b99ead4845fe2dcb6adfe84381e (diff) |
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
-rw-r--r-- | omx/Makefile.am | 2 | ||||
-rw-r--r-- | omx/gstomxvideo.c | 151 | ||||
-rw-r--r-- | omx/gstomxvideo.h | 55 | ||||
-rw-r--r-- | omx/gstomxvideodec.c | 142 | ||||
-rw-r--r-- | omx/gstomxvideoenc.c | 144 |
5 files changed, 233 insertions, 261 deletions
diff --git a/omx/Makefile.am b/omx/Makefile.am index 9006214..bcdd60c 100644 --- a/omx/Makefile.am +++ b/omx/Makefile.am @@ -13,6 +13,7 @@ endif libgstomx_la_SOURCES = \ gstomx.c \ gstomxbufferpool.c \ + gstomxvideo.c \ gstomxvideodec.c \ gstomxvideoenc.c \ gstomxaudioenc.c \ @@ -31,6 +32,7 @@ libgstomx_la_SOURCES = \ noinst_HEADERS = \ gstomx.h \ + gstomxvideo.h \ gstomxvideodec.h \ gstomxvideoenc.h \ gstomxaudioenc.h \ 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 (¶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; +} diff --git a/omx/gstomxvideo.h b/omx/gstomxvideo.h new file mode 100644 index 0000000..df81654 --- /dev/null +++ b/omx/gstomxvideo.h @@ -0,0 +1,55 @@ +/* + * 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__ */ diff --git a/omx/gstomxvideodec.c b/omx/gstomxvideodec.c index 3b6605a..af93aba 100644 --- a/omx/gstomxvideodec.c +++ b/omx/gstomxvideodec.c @@ -48,6 +48,7 @@ #include <string.h> #include "gstomxbufferpool.h" +#include "gstomxvideo.h" #include "gstomxvideodec.h" GST_DEBUG_CATEGORY_STATIC (gst_omx_video_dec_debug_category); @@ -402,43 +403,6 @@ gst_omx_video_dec_change_state (GstElement * element, GstStateChange transition) 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) @@ -1328,7 +1292,8 @@ gst_omx_video_dec_loop (GstOMXVideoDec * self) (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 @@ -1643,86 +1608,6 @@ gst_omx_video_dec_stop (GstVideoDecoder * decoder) 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) { @@ -1745,16 +1630,11 @@ 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; @@ -1769,7 +1649,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self) 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; } @@ -1785,7 +1665,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self) 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); @@ -1794,7 +1674,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self) 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; @@ -1808,7 +1688,7 @@ gst_omx_video_dec_negotiate (GstOMXVideoDec * self) /* 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, diff --git a/omx/gstomxvideoenc.c b/omx/gstomxvideoenc.c index 07c9d77..9dcbbd1 100644 --- a/omx/gstomxvideoenc.c +++ b/omx/gstomxvideoenc.c @@ -26,6 +26,7 @@ #include <gst/video/gstvideometa.h> #include <string.h> +#include "gstomxvideo.h" #include "gstomxvideoenc.h" GST_DEBUG_CATEGORY_STATIC (gst_omx_video_enc_debug_category); @@ -539,43 +540,6 @@ gst_omx_video_enc_change_state (GstElement * element, GstStateChange transition) 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) @@ -782,7 +746,8 @@ gst_omx_video_enc_loop (GstOMXVideoEnc * self) (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); @@ -958,83 +923,6 @@ gst_omx_video_enc_stop (GstVideoEncoder * encoder) 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) @@ -1097,7 +985,9 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, 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) { @@ -1115,7 +1005,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, } } 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; @@ -1123,7 +1013,7 @@ gst_omx_video_enc_set_format (GstVideoEncoder * encoder, } } 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; @@ -1781,24 +1671,18 @@ static GstCaps * 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 = |