#include <gst/gst.h>
#include <gst/gstelement.h>
#include <gst/app/gstappsrc.h>
+#include <gst/pbutils/pbutils.h>
+#include <gst/tag/tag.h>
/*
* Internal Implementation
static gboolean __mc_gst_init_gstreamer();
static int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime);
-static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name);
+static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name);
static mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core);
static void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data);
static int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data);
int(*adec_wma_vtable[])() = {&__mc_fill_input_buffer_with_packet, /* WMA Decoder Vtable */
&__mc_fill_packet_with_output_buffer};
+int(*aenc_opus_vtable[])() = {&__mc_fill_input_buffer_with_packet, /* Opus Encoder Vtable */
+ &__mc_fill_aenc_packet_with_output_buffer};
+
#define MEDIACODEC_ELEMENT_SET_STATE(x_element, x_state) \
do { \
LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \
return MC_ERROR;
}
- if (buf_data != NULL) {
- gst_buffer_append_memory(mcbuffer->buffer,
- gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0,
- buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb));
- LOGD("packet data apended");
- }
+ if (buf_data == NULL)
+ return MC_ERROR;
+
+ gst_buffer_append_memory(mcbuffer->buffer,
+ gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0,
+ buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb));
+ LOGD("packet data apended");
return ret;
}
s = gst_caps_get_structure(peercaps, 0);
codec_data = gst_structure_get_value(s, "codec_data");
+ if (codec_data == NULL && gst_structure_has_field(s, "streamheader"))
+ codec_data = gst_structure_get_value(s, "streamheader");
+
core->codec_data = GST_BUFFER(g_value_dup_boxed(codec_data));
gst_caps_unref(peercaps);
}
__mc_gst_caps_set_buffer_array(core->caps, "streamheader", header1, header2, NULL);
gst_buffer_unref(header1);
gst_buffer_unref(header2);
+ } else if (core->codec_id == MEDIACODEC_OPUS) {
+ const GstTagList *tags;
+ GstTagList *empty_tags = NULL;
+ GstBuffer *header, *comments;
+ guint8 *decoding_channel_mapping = NULL;
+ mc_gst_port_def_t *port_def = &core->ports[in_port_index]->port_def;
+
+ header = gst_codec_utils_opus_create_header(port_def->info.audio.samplerate,
+ port_def->info.audio.channel,
+ 0, /* channel mapping family */
+ 1, /* stream count */
+ 0, /* coupled count */
+ decoding_channel_mapping,
+ 0, /* FIXME: look ahead configured value */
+ 0);
+ tags = gst_tag_setter_get_tag_list(GST_TAG_SETTER(core->codec));
+ if (!tags)
+ tags = empty_tags = gst_tag_list_new_empty();
+ comments = gst_tag_list_to_vorbiscomment_buffer(tags, (const guint8 *) "OpusTags",
+ 8, "Encoded with GStreamer opusenc");
+ core->caps = gst_codec_utils_opus_create_caps_from_header(header, comments);
+ if (empty_tags)
+ gst_tag_list_unref(empty_tags);
+ gst_buffer_unref(header);
+ gst_buffer_unref(comments);
} else {
LOGE("Not support case of Stream header Caps");
}
break;
case MEDIACODEC_VORBIS:
case MEDIACODEC_FLAC:
+ case MEDIACODEC_OPUS:
if (codec_config) {
ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE);
if (ret != MC_ERROR_NONE)
NULL);
}
break;
+ case MEDIACODEC_OPUS:
+ if (core->encoder) {
+ gst_caps_set_simple(caps,
+ "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth),
+ "layout", G_TYPE_STRING, "interleaved", NULL);
+ } else {
+ LOGD("[MC_NOT_SUPPORTED] opus decoder is not supported yet!!!");
+ return NULL;
+ }
+ break;
default:
break;
}
LOGE("format : %s", port_def->info.video.format);
} else {
gst_caps_set_simple(caps,
- "parsed", G_TYPE_BOOLEAN, TRUE, /* FIXME different from sw */
+ "parsed", G_TYPE_BOOLEAN, TRUE, /* FIXME different from sw */
"alignment", G_TYPE_STRING, "au",
"stream-format", G_TYPE_STRING, "byte-stream",
"framerate", GST_TYPE_FRACTION, 30, 1,
switch (id) {
case MEDIACODEC_AAC:
- if (encoder) {
+ if (encoder)
core->vtable = aenc_aac_vtable;
- } else {
+ else
core->vtable = adec_aac_vtable;
- }
break;
case MEDIACODEC_AAC_HE:
case MEDIACODEC_AAC_HE_PS:
break;
case MEDIACODEC_AMR_NB:
LOGD("amrnb vtable");
- if (encoder) {
+ if (encoder)
core->vtable = aenc_amrnb_vtable;
- } else {
+ else
core->vtable = adec_amrnb_vtable;
- }
break;
case MEDIACODEC_AMR_WB:
LOGD("amrwb vtable - Only support decoder");
break;
case MEDIACODEC_VORBIS:
LOGD("vorbis vtable");
- if (encoder) {
- LOGD("[MC_NOT_SUPPORTED] vorbis encoder is not supported yet!!!");
+ if (encoder)
return MC_NOT_SUPPORTED;
- } else {
+ else
core->vtable = adec_vorbis_vtable;
- }
break;
case MEDIACODEC_FLAC:
LOGD("flac vtable");
core->vtable = adec_flac_vtable;
}
break;
+ case MEDIACODEC_OPUS:
+ LOGD("opus vtable");
+ if (encoder)
+ core->vtable = aenc_opus_vtable;
+ else
+ core->vtable = adec_vtable;
+ break;
case MEDIACODEC_WMAV1:
case MEDIACODEC_WMAV2:
case MEDIACODEC_WMAPRO:
if (encoder) {
core->vtable = is_hw ? venc_h263_hw_vtable : venc_h263_sw_vtable;
} else {
- if (is_hw) {
+ if (is_hw)
core->vtable = vdec_h263_hw_vtable;
- } else {
+ else
core->vtable = vdec_h263_sw_vtable;
- }
}
break;
case MEDIACODEC_MPEG4:
LOGD("mpeg4 vtable");
- if (encoder) {
+ if (encoder)
core->vtable = is_hw ? venc_mpeg4_hw_vtable : venc_mpeg4_sw_vtable;
- } else {
+ else
core->vtable = is_hw ? vdec_mpeg4_hw_vtable : vdec_mpeg4_sw_vtable;
- }
break;
case MEDIACODEC_H264:
LOGD("h264 vtable");
if (encoder) {
core->vtable = is_hw ? venc_h264_hw_vtable : venc_vtable;
} else {
- if (is_hw) {
+ if (is_hw)
core->vtable = vdec_h264_hw_vtable;
- } else {
+ else
core->vtable = vdec_h264_sw_vtable;
- }
}
break;
default:
return FALSE;
}
-mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name)
+mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name)
{
GstBus *bus = NULL;
mcbuffer = (GstMCBuffer *)g_malloc0(sizeof(GstMCBuffer));
+ if (mcbuffer == NULL) {
+ LOGE("malloc fail");
+ return NULL;
+ }
+
mcbuffer->buffer = gst_buffer_new();
mcbuffer->buf_size = 0;
case MEDIACODEC_AMR_WB:
mime = MEDIA_FORMAT_AMR_WB;
break;
+ case MEDIACODEC_OPUS:
+ if (core->encoder)
+ mime = MEDIA_FORMAT_OPUS;
+ else
+ mime = MEDIA_FORMAT_PCM_S16LE;
+ break;
default:
- LOGE("NOT SUPPORTED!!!!");
+ LOGE("NOT SUPPORTED!!!! 0x%x ", core->codec_id);
break;
}
return mime;
#define ADTS_HEADER_SIZE 7
#define AMRNB_PCM_INPUT_SIZE 320
#define AMRWB_PCM_INPUT_SIZE 640
+#define OPUS_PCM_INPUT_SIZE 4096
#define CHECK_BIT(x, y) (((x) >> (y)) & 0x01)
#define GET_IS_ENCODER(x) CHECK_BIT(x, 0)
app->offset += *size;
}
+void opusenc_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data)
+{
+ gint read_size = OPUS_PCM_INPUT_SIZE;
+ gint offset = app->length - app->offset;
+
+ *have_frame = TRUE;
+ *data = app->data + app->offset;
+
+ if (read_size >= offset)
+ *size = offset;
+ else
+ *size = read_size;
+
+ app->offset += *size;
+}
+
/**
* Extract Input data for AAC decoder
* (case of (LC profile) ADTS format)
mime = MEDIA_FORMAT_AMR_WB;
}
break;
+ case MEDIACODEC_OPUS:
+ if (encoder) {
+ extractor = opusenc_extractor;
+ mime = MEDIA_FORMAT_OPUS; /* FIXME need to check according to verdor */
+ *codec_mime = MEDIA_FORMAT_OPUS;
+ app->is_amr_nb = FALSE;
+ } else {
+ mime = MEDIA_FORMAT_OPUS;
+ *codec_mime = MEDIA_FORMAT_OPUS;
+ }
+ break;
+
default:
LOGE("NOT SUPPORTED!!!!");
break;
media_format_set_audio_channel(fmt, app->channel);
media_format_set_audio_samplerate(fmt, app->samplerate);
media_format_set_audio_bit(fmt, app->bit);
+ media_format_set_audio_avg_bps(fmt, app->bitrate);
media_format_create(&codec_format);
media_format_set_audio_mime(codec_format, codec_mime);
g_print(" WMAV2 = 13\n");
g_print(" WMAPRO = 14\n");
g_print(" WMALSL = 15\n");
+ g_print(" OPUS = 16\n");
g_print(" -------------------\n");
- g_print(" H261 = 16\n");
- g_print(" H263 = 17\n");
- g_print(" H264 = 18\n");
- g_print(" MJPEG = 19\n");
- g_print(" MPEG1 = 20\n");
- g_print(" MPEG2 = 21\n");
- g_print(" MPEG4 = 22\n");
- g_print(" HEVC = 23\n");
- g_print(" VP8 = 24\n");
- g_print(" VP9 = 25\n");
+ g_print(" H261 = 17\n");
+ g_print(" H263 = 18\n");
+ g_print(" H264 = 19\n");
+ g_print(" MJPEG = 20\n");
+ g_print(" MPEG1 = 21\n");
+ g_print(" MPEG2 = 22\n");
+ g_print(" MPEG4 = 23\n");
+ g_print(" HEVC = 24\n");
+ g_print(" VP8 = 25\n");
+ g_print(" VP9 = 26\n");
g_print(" -------------------\n");
g_print("*** Flags : Select Combination Number (e.g. DEOCDER + TYPE_SW = 10)\n");
g_print(" CODEC : ENCODER = 1 DECODER = 2\n");
break;
case CURRENT_STATUS_SET_CODEC:
{
- gint ids[] = { 0x1010, 0x1020, 0x1030, 0x1040, 0x1041, 0x1050, 0x1060, 0x1061, 0x1062,
- 0x1070, 0x1080, 0x1090, 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x2010, 0x2020,
- 0x2030, 0x2040, 0x2050, 0x2060, 0x2070, 0x2080, 0x2090, 0x20A0, 0x20B0 };
+ gint ids[] = { 0x1010, 0x1020, 0x1030, 0x1040, 0x1041,
+ 0x1050, 0x1060, 0x1061, 0x1062, 0x1070,
+ 0x1080, 0x1090, 0x10A0, 0x10A1, 0x10A2,
+ 0x10A3, 0x10D0, 0x2010, 0x2020, 0x2030,
+ 0x2040, 0x2050, 0x2060, 0x2070, 0x2080,
+ 0x2090, 0x20A0, 0x20B0 };
if (cnt == 0) {
gint n_sizes = G_N_ELEMENTS(ids);
return "VP9";
case MEDIACODEC_VC1:
return "VC1";
+ case MEDIACODEC_OPUS:
+ return "OPUS";
default:
return "NONE";
}