From a039499bf16f07d148d5dc16618f054d26f349ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 23 Nov 2011 20:03:32 +0000 Subject: [PATCH 01/10] basevideodecoder: add API to drop a frame and post a QoS message on the bus https://bugzilla.gnome.org/show_bug.cgi?id=640017 API: gst_base_video_decoder_drop_frame() --- gst-libs/gst/video/gstbasevideodecoder.c | 132 ++++++++++++++++++----- gst-libs/gst/video/gstbasevideodecoder.h | 7 +- 2 files changed, 113 insertions(+), 26 deletions(-) diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index 80cb7b9fd7..24bf16fbeb 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -969,6 +969,9 @@ gst_base_video_decoder_reset (GstBaseVideoDecoder * base_video_decoder, base_video_decoder->current_frame = NULL; } + base_video_decoder->dropped = 0; + base_video_decoder->processed = 0; + GST_BASE_VIDEO_CODEC (base_video_decoder)->system_frame_number = 0; base_video_decoder->base_picture_number = 0; @@ -1365,30 +1368,12 @@ gst_base_video_decoder_new_frame (GstBaseVideoDecoder * base_video_decoder) return frame; } -/** - * gst_base_video_decoder_finish_frame: - * @base_video_decoder: a #GstBaseVideoDecoder - * @frame: a decoded #GstVideoFrame - * - * @frame should have a valid decoded data buffer, whose metadata fields - * are then appropriately set according to frame data and pushed downstream. - * If no output data is provided, @frame is considered skipped. - * In any case, the frame is considered finished and released. - * - * Returns: a #GstFlowReturn resulting from sending data downstream - */ -GstFlowReturn -gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, - GstVideoFrame * frame) +static void +gst_base_video_decoder_prepare_finish_frame (GstBaseVideoDecoder * + base_video_decoder, GstVideoFrame * frame) { - GstVideoState *state = &GST_BASE_VIDEO_CODEC (base_video_decoder)->state; - GstBuffer *src_buffer; - GstFlowReturn ret = GST_FLOW_OK; GList *l, *events = NULL; - GST_LOG_OBJECT (base_video_decoder, "finish frame"); - GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder); - #ifndef GST_DISABLE_GST_DEBUG GST_LOG_OBJECT (base_video_decoder, "n %d in %d out %d", g_list_length (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames), @@ -1474,8 +1459,106 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, } } base_video_decoder->last_timestamp = frame->presentation_timestamp; +} - /* no buffer data means this frame is skipped/dropped */ +static void +gst_base_video_decoder_do_finish_frame (GstBaseVideoDecoder * dec, + GstVideoFrame * frame) +{ + GST_BASE_VIDEO_CODEC (dec)->frames = + g_list_remove (GST_BASE_VIDEO_CODEC (dec)->frames, frame); + + if (frame->src_buffer) + gst_buffer_unref (frame->src_buffer); + + gst_base_video_codec_free_frame (frame); +} + +/** + * gst_base_video_decoder_drop_frame: + * @dec: a #GstBaseVideoDecoder + * @frame: the #GstVideoFrame to drop + * + * Similar to gst_base_video_decoder_finish_frame(), but drops @frame in any + * case and posts a QoS message with the frame's details on the bus. + * In any case, the frame is considered finished and released. + * + * Returns: a #GstFlowReturn, usually GST_FLOW_OK. + * + * Since: 0.10.23 + */ +GstFlowReturn +gst_base_video_decoder_drop_frame (GstBaseVideoDecoder * dec, + GstVideoFrame * frame) +{ + GstClockTime stream_time, jitter, earliest_time, qostime, timestamp; + GstSegment *segment; + GstMessage *qos_msg; + gdouble proportion; + + GST_LOG_OBJECT (dec, "drop frame"); + + GST_BASE_VIDEO_CODEC_STREAM_LOCK (dec); + + gst_base_video_decoder_prepare_finish_frame (dec, frame); + + GST_DEBUG_OBJECT (dec, "dropping frame %" GST_TIME_FORMAT, + GST_TIME_ARGS (frame->presentation_timestamp)); + + dec->dropped++; + + /* post QoS message */ + timestamp = frame->presentation_timestamp; + proportion = GST_BASE_VIDEO_CODEC (dec)->proportion; + segment = &GST_BASE_VIDEO_CODEC (dec)->segment; + stream_time = + gst_segment_to_stream_time (segment, GST_FORMAT_TIME, timestamp); + qostime = gst_segment_to_running_time (segment, GST_FORMAT_TIME, timestamp); + earliest_time = GST_BASE_VIDEO_CODEC (dec)->earliest_time; + jitter = GST_CLOCK_DIFF (qostime, earliest_time); + qos_msg = gst_message_new_qos (GST_OBJECT_CAST (dec), FALSE, + qostime, stream_time, timestamp, GST_CLOCK_TIME_NONE); + gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000); + gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, + dec->processed, dec->dropped); + gst_element_post_message (GST_ELEMENT_CAST (dec), qos_msg); + + /* now free the frame */ + gst_base_video_decoder_do_finish_frame (dec, frame); + + GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (dec); + + return GST_FLOW_OK; +} + +/** + * gst_base_video_decoder_finish_frame: + * @base_video_decoder: a #GstBaseVideoDecoder + * @frame: a decoded #GstVideoFrame + * + * @frame should have a valid decoded data buffer, whose metadata fields + * are then appropriately set according to frame data and pushed downstream. + * If no output data is provided, @frame is considered skipped. + * In any case, the frame is considered finished and released. + * + * Returns: a #GstFlowReturn resulting from sending data downstream + */ +GstFlowReturn +gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, + GstVideoFrame * frame) +{ + GstVideoState *state = &GST_BASE_VIDEO_CODEC (base_video_decoder)->state; + GstBuffer *src_buffer; + GstFlowReturn ret = GST_FLOW_OK; + + GST_LOG_OBJECT (base_video_decoder, "finish frame"); + GST_BASE_VIDEO_CODEC_STREAM_LOCK (base_video_decoder); + + gst_base_video_decoder_prepare_finish_frame (base_video_decoder, frame); + + base_video_decoder->processed++; + + /* no buffer data means this frame is skipped */ if (!frame->src_buffer) { GST_DEBUG_OBJECT (base_video_decoder, "skipping frame %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->presentation_timestamp)); @@ -1584,9 +1667,8 @@ gst_base_video_decoder_finish_frame (GstBaseVideoDecoder * base_video_decoder, } done: - GST_BASE_VIDEO_CODEC (base_video_decoder)->frames = - g_list_remove (GST_BASE_VIDEO_CODEC (base_video_decoder)->frames, frame); - gst_base_video_codec_free_frame (frame); + + gst_base_video_decoder_do_finish_frame (base_video_decoder, frame); GST_BASE_VIDEO_CODEC_STREAM_UNLOCK (base_video_decoder); diff --git a/gst-libs/gst/video/gstbasevideodecoder.h b/gst-libs/gst/video/gstbasevideodecoder.h index c128b18192..a3b81fe44b 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.h +++ b/gst-libs/gst/video/gstbasevideodecoder.h @@ -182,6 +182,10 @@ struct _GstBaseVideoDecoder int reorder_depth; int distance_from_sync; + /* qos messages: frames dropped/processed */ + guint dropped; + guint processed; + /* FIXME before moving to base */ void *padding[GST_PADDING_LARGE]; }; @@ -267,7 +271,8 @@ GstClockTimeDiff gst_base_video_decoder_get_max_decode_time ( GstVideoFrame *frame); GstFlowReturn gst_base_video_decoder_finish_frame (GstBaseVideoDecoder *base_video_decoder, GstVideoFrame *frame); - +GstFlowReturn gst_base_video_decoder_drop_frame (GstBaseVideoDecoder *dec, + GstVideoFrame *frame); GType gst_base_video_decoder_get_type (void); G_END_DECLS From ca772ed3211b7faad8452af105f2643af43ccdac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 25 Nov 2011 11:36:14 +0000 Subject: [PATCH 02/10] vp8dec: use new basevideodecoder API to drop frames and get QoS messages posted --- ext/vp8/gstvp8dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/vp8/gstvp8dec.c b/ext/vp8/gstvp8dec.c index 4376f4be70..248f444d4c 100644 --- a/ext/vp8/gstvp8dec.c +++ b/ext/vp8/gstvp8dec.c @@ -475,7 +475,7 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame) if (deadline < 0) { GST_LOG_OBJECT (dec, "Skipping late frame (%f s past deadline)", (double) -deadline / GST_SECOND); - gst_base_video_decoder_finish_frame (decoder, frame); + gst_base_video_decoder_drop_frame (decoder, frame); } else { ret = gst_base_video_decoder_alloc_src_frame (decoder, frame); From f78e9e168449ee8be18e6cd6d95afd73faaad733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 25 Nov 2011 11:37:39 +0000 Subject: [PATCH 03/10] basevideodecoder: some more debug logging --- gst-libs/gst/video/gstbasevideodecoder.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index 24bf16fbeb..f396ca072b 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -1398,9 +1398,12 @@ gst_base_video_decoder_prepare_finish_frame (GstBaseVideoDecoder * break; } - for (l = g_list_last (events); l; l = l->prev) + for (l = g_list_last (events); l; l = l->prev) { + GST_LOG_OBJECT (base_video_decoder, "pushing %s event", + GST_EVENT_TYPE_NAME (l->data)); gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder), l->data); + } g_list_free (events); if (GST_CLOCK_TIME_IS_VALID (frame->presentation_timestamp)) { From d3fda8a6442fc1374dbb7dd1b4a999ef300ed680 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 25 Nov 2011 15:49:05 +0100 Subject: [PATCH 04/10] tests: add unit test for voamrwbenc --- tests/check/Makefile.am | 7 ++ tests/check/elements/voamrwbenc.c | 186 ++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 tests/check/elements/voamrwbenc.c diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 7ee8231b09..ca7ced8b4a 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -57,6 +57,12 @@ else check_voaacenc = endif +if USE_VOAMRWBENC +check_voamrwbenc = elements/voamrwbenc +else +check_voamrwbenc = +endif + if USE_EXIF check_jifmux = elements/jifmux else @@ -162,6 +168,7 @@ check_PROGRAMS = \ $(check_faac) \ $(check_faad) \ $(check_voaacenc) \ + $(check_voamrwbenc) \ $(check_mpeg2enc) \ $(check_mplex) \ $(check_ofa) \ diff --git a/tests/check/elements/voamrwbenc.c b/tests/check/elements/voamrwbenc.c new file mode 100644 index 0000000000..18f3cc239e --- /dev/null +++ b/tests/check/elements/voamrwbenc.c @@ -0,0 +1,186 @@ +/* GStreamer + * + * unit test for voamrwbenc + * + * Copyright (C) <2011> Mark Nauwelaerts + * + * 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. + */ + +#include + +#include + +/* For ease of programming we use globals to keep refs for our floating + * src and sink pads we create; otherwise we always have to do get_pad, + * get_peer, and then remove references in every test function */ +static GstPad *mysrcpad, *mysinkpad; + +#define AUDIO_CAPS_STRING "audio/x-raw-int, " \ + "rate = (int) 16000, " \ + "channels = (int) 1, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (boolean) true, " \ + "endianness = (int) BYTE_ORDER " + +#define AMRWB_CAPS_STRING "audio/AMR-WB" + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (AMRWB_CAPS_STRING)); + + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (AUDIO_CAPS_STRING)); + + +static GstElement * +setup_voamrwbenc (void) +{ + GstElement *voamrwbenc; + + GST_DEBUG ("setup_voamrwbenc"); + voamrwbenc = gst_check_setup_element ("voamrwbenc"); + /* ensure mode as expected */ + g_object_set (voamrwbenc, "band-mode", 0, NULL); + mysrcpad = gst_check_setup_src_pad (voamrwbenc, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (voamrwbenc, &sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return voamrwbenc; +} + +static void +cleanup_voamrwbenc (GstElement * voamrwbenc) +{ + GST_DEBUG ("cleanup_aacenc"); + gst_element_set_state (voamrwbenc, GST_STATE_NULL); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (voamrwbenc); + gst_check_teardown_sink_pad (voamrwbenc); + gst_check_teardown_element (voamrwbenc); +} + +static void +do_test (void) +{ + GstElement *voamrwbenc; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint i, num_buffers; + const gint nbuffers = 10; + + voamrwbenc = setup_voamrwbenc (); + fail_unless (gst_element_set_state (voamrwbenc, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + /* corresponds to audio buffer mentioned in the caps */ + inbuffer = gst_buffer_new_and_alloc (320 * nbuffers * 2); + /* makes valgrind's memcheck happier */ + memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer)); + caps = gst_caps_from_string (AUDIO_CAPS_STRING); + + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* send eos to have all flushed if needed */ + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE); + + num_buffers = g_list_length (buffers); + fail_unless_equals_int (num_buffers, nbuffers); + + /* clean up buffers */ + for (i = 0; i < num_buffers; ++i) { + gint size; + guint8 *data; + GstClockTime time, dur; + + outbuffer = GST_BUFFER (buffers->data); + fail_if (outbuffer == NULL); + + data = GST_BUFFER_DATA (outbuffer); + size = GST_BUFFER_SIZE (outbuffer); + + /* at least for mode 0 */ + fail_unless (size == 18); + fail_unless ((data[0] & 0x83) == 0); + fail_unless (((data[0] >> 3) & 0xF) == 0); + + time = GST_BUFFER_TIMESTAMP (outbuffer); + dur = GST_BUFFER_DURATION (outbuffer); + fail_unless (time == 20 * GST_MSECOND * i); + fail_unless (dur == 20 * GST_MSECOND); + + buffers = g_list_remove (buffers, outbuffer); + + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + gst_buffer_unref (outbuffer); + outbuffer = NULL; + } + + cleanup_voamrwbenc (voamrwbenc); + g_list_free (buffers); + buffers = NULL; +} + +GST_START_TEST (test_enc) +{ + do_test (); +} + +GST_END_TEST; + + +static Suite * +voamrwbenc_suite (void) +{ + Suite *s = suite_create ("voamrwbenc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_enc); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = voamrwbenc_suite (); + SRunner *sr = srunner_create (s); + + gst_check_init (&argc, &argv); + + srunner_run_all (sr, CK_NORMAL); + nf = srunner_ntests_failed (sr); + srunner_free (sr); + + return nf; +} From 5f85454020b8ae87d75294c887aacfc5391bc001 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 25 Nov 2011 12:39:20 +0000 Subject: [PATCH 05/10] opusdec: fix bogus assertion --- ext/opus/gstopusdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c index 58283973a2..cc1bdb2a11 100644 --- a/ext/opus/gstopusdec.c +++ b/ext/opus/gstopusdec.c @@ -224,7 +224,8 @@ gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf) const GstAudioChannelPosition *pos = NULL; g_return_val_if_fail (gst_opus_header_is_id_header (buf), GST_FLOW_ERROR); - g_return_val_if_fail (dec->n_channels != data[9], GST_FLOW_ERROR); + g_return_val_if_fail (dec->n_channels == 0 + || dec->n_channels == data[9], GST_FLOW_ERROR); dec->n_channels = data[9]; dec->pre_skip = GST_READ_UINT16_LE (data + 10); From f78c83a0b6353102455fa8c74848a4e2c7b138c5 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 25 Nov 2011 12:40:31 +0000 Subject: [PATCH 06/10] opusenc: do not cause the decoder to apply the channel mapping again Since we already reorder channels, we do not want to write that reordering in the header, or the decoder will do it again. --- ext/opus/gstopusenc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index 6dad531156..11ddcc127e 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -532,13 +532,17 @@ gst_opus_enc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) static gboolean gst_opus_enc_setup (GstOpusEnc * enc) { - int error = OPUS_OK; + int error = OPUS_OK, n; + guint8 trivial_mapping[256]; GST_DEBUG_OBJECT (enc, "setup"); + for (n = 0; n < 256; ++n) + trivial_mapping[n] = n; + enc->state = opus_multistream_encoder_create (enc->sample_rate, enc->n_channels, - (enc->n_channels + 1) / 2, enc->n_channels / 2, enc->channel_mapping, + (enc->n_channels + 1) / 2, enc->n_channels / 2, trivial_mapping, enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP, &error); if (!enc->state || error != OPUS_OK) From 2e0e11867634d513a448cdf5d07984cf81e0a0ed Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 25 Nov 2011 12:46:55 +0000 Subject: [PATCH 07/10] opusparse: remove dead assigments We now only keep a ref to the headers for later reuse. --- ext/opus/gstopusparse.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ext/opus/gstopusparse.c b/ext/opus/gstopusparse.c index 8627f93028..fae62007e3 100644 --- a/ext/opus/gstopusparse.c +++ b/ext/opus/gstopusparse.c @@ -279,16 +279,11 @@ gst_opus_parse_parse_frame (GstBaseParse * base, GstBaseParseFrame * frame) if (!parse->header_sent) { GstCaps *caps; - guint8 channels, channel_mapping_family, channel_mapping[256]; - const guint8 *data = GST_BUFFER_DATA (frame->buffer); + guint8 channels; /* Opus streams can decode to 1 or 2 channels, so use the header value if we have one, or 2 otherwise */ if (is_idheader) { - channels = data[9]; - channel_mapping_family = data[18]; - /* header probing will already have done the size check */ - memcpy (channel_mapping, GST_BUFFER_DATA (frame->buffer) + 21, channels); gst_buffer_replace (&parse->id_header, frame->buffer); GST_DEBUG_OBJECT (parse, "Found ID header, keeping"); return GST_BASE_PARSE_FLOW_DROPPED; @@ -305,6 +300,7 @@ gst_opus_parse_parse_frame (GstBaseParse * base, GstBaseParseFrame * frame) gst_opus_header_create_caps_from_headers (&caps, &parse->headers, parse->id_header, parse->comment_header); } else { + guint8 channel_mapping_family, channel_mapping[256]; GST_INFO_OBJECT (parse, "No headers, blindly setting up canonical stereo"); channels = 2; From 65079e3adaa34831202bed7e650f4f0cb47ec3ff Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 25 Nov 2011 12:47:42 +0000 Subject: [PATCH 08/10] opus: add some more debug information about channel mapping --- ext/opus/gstopuscommon.c | 16 ++++++++++++++++ ext/opus/gstopuscommon.h | 1 + ext/opus/gstopusdec.c | 1 + ext/opus/gstopusenc.c | 10 ++++++---- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/ext/opus/gstopuscommon.c b/ext/opus/gstopuscommon.c index fc3e0376b9..426c5b8973 100644 --- a/ext/opus/gstopuscommon.c +++ b/ext/opus/gstopuscommon.c @@ -70,3 +70,19 @@ const GstAudioChannelPosition gst_opus_channel_positions[][8] = { GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, GST_AUDIO_CHANNEL_POSITION_LFE}, }; + +const char *gst_opus_channel_names[] = { + "mono", + "front left", + "front right", + "rear center", + "rear left", + "rear right", + "lfe", + "front center", + "front left of center", + "front right of center", + "side left", + "side right", + "none" +}; diff --git a/ext/opus/gstopuscommon.h b/ext/opus/gstopuscommon.h index 96a303e303..65b944e9e2 100644 --- a/ext/opus/gstopuscommon.h +++ b/ext/opus/gstopuscommon.h @@ -27,6 +27,7 @@ G_BEGIN_DECLS extern const GstAudioChannelPosition gst_opus_channel_positions[][8]; +extern const char *gst_opus_channel_names[]; G_END_DECLS diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c index cc1bdb2a11..ee1886040d 100644 --- a/ext/opus/gstopusdec.c +++ b/ext/opus/gstopusdec.c @@ -294,6 +294,7 @@ gst_opus_dec_parse_header (GstOpusDec * dec, GstBuffer * buf) dec->sample_rate); if (pos) { + GST_DEBUG_OBJECT (dec, "Setting channel positions on caps"); gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); } diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index 11ddcc127e..a926bbdb4c 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -466,7 +466,8 @@ gst_opus_enc_setup_channel_mapping (GstOpusEnc * enc, const GstAudioInfo * info) GstAudioChannelPosition pos = GST_AUDIO_INFO_POSITION (info, n); int c; - GST_DEBUG_OBJECT (enc, "Channel %d has position %d", n, pos); + GST_DEBUG_OBJECT (enc, "Channel %d has position %d (%s)", n, pos, + gst_opus_channel_names[pos]); for (c = 0; c < enc->n_channels; ++c) { if (gst_opus_channel_positions[enc->n_channels - 1][c] == pos) { GST_DEBUG_OBJECT (enc, "Found in Vorbis mapping as channel %d", c); @@ -476,12 +477,13 @@ gst_opus_enc_setup_channel_mapping (GstOpusEnc * enc, const GstAudioInfo * info) if (c == enc->n_channels) { /* We did not find that position, so use undefined */ GST_WARNING_OBJECT (enc, - "Position %d not found in Vorbis mapping, using unknown mapping", - pos); + "Position %d (%s) not found in Vorbis mapping, using unknown mapping", + pos, gst_opus_channel_positions[pos]); enc->channel_mapping_family = 255; return; } - GST_DEBUG_OBJECT (enc, "Mapping output channel %d to %d", c, n); + GST_DEBUG_OBJECT (enc, "Mapping output channel %d to %d (%s)", c, n, + gst_opus_channel_names[pos]); enc->channel_mapping[c] = n; } GST_INFO_OBJECT (enc, "Permutation found, using Vorbis mapping"); From 631f42eee82c17c352d7fcab96eb387650018b61 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 25 Nov 2011 14:00:18 +0000 Subject: [PATCH 09/10] opusenc: only use mono streams for > 2 channels I'm getting odd results with packing streams into stereo streams, and using only mono streams is enough in all cases. --- ext/opus/gstopusenc.c | 2 +- ext/opus/gstopusheader.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index a926bbdb4c..c6604c2196 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -544,7 +544,7 @@ gst_opus_enc_setup (GstOpusEnc * enc) enc->state = opus_multistream_encoder_create (enc->sample_rate, enc->n_channels, - (enc->n_channels + 1) / 2, enc->n_channels / 2, trivial_mapping, + enc->n_channels, 0, trivial_mapping, enc->audio_or_voip ? OPUS_APPLICATION_AUDIO : OPUS_APPLICATION_VOIP, &error); if (!enc->state || error != OPUS_OK) diff --git a/ext/opus/gstopusheader.c b/ext/opus/gstopusheader.c index 1aa3b0d01b..42df7b35fb 100644 --- a/ext/opus/gstopusheader.c +++ b/ext/opus/gstopusheader.c @@ -44,8 +44,8 @@ gst_opus_enc_create_id_buffer (gint nchannels, gint sample_rate, gst_byte_writer_put_uint16_le (&bw, 0); /* output gain */ gst_byte_writer_put_uint8 (&bw, channel_mapping_family); if (channel_mapping_family > 0) { - gst_byte_writer_put_uint8 (&bw, (nchannels + 1) / 2); - gst_byte_writer_put_uint8 (&bw, nchannels / 2); + gst_byte_writer_put_uint8 (&bw, nchannels); + gst_byte_writer_put_uint8 (&bw, 0); gst_byte_writer_put_data (&bw, channel_mapping, nchannels); } From 43190ea0f8537c437aaf291f7ade2cfc4241a440 Mon Sep 17 00:00:00 2001 From: Danilo Cesar Lemes de Paula Date: Fri, 25 Nov 2011 11:41:19 -0200 Subject: [PATCH 10/10] opusenc: Fixing "Unused var" compiling error for opus codec https://bugzilla.gnome.org/show_bug.cgi?id=664815 --- ext/opus/gstopusdec.c | 2 -- ext/opus/gstopusenc.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/ext/opus/gstopusdec.c b/ext/opus/gstopusdec.c index ee1886040d..89639b12b8 100644 --- a/ext/opus/gstopusdec.c +++ b/ext/opus/gstopusdec.c @@ -118,11 +118,9 @@ gst_opus_dec_class_init (GstOpusDecClass * klass) { GObjectClass *gobject_class; GstAudioDecoderClass *adclass; - GstElementClass *gstelement_class; gobject_class = (GObjectClass *) klass; adclass = (GstAudioDecoderClass *) klass; - gstelement_class = (GstElementClass *) klass; gobject_class->set_property = gst_opus_dec_set_property; gobject_class->get_property = gst_opus_dec_get_property; diff --git a/ext/opus/gstopusenc.c b/ext/opus/gstopusenc.c index c6604c2196..8ca1158c99 100644 --- a/ext/opus/gstopusenc.c +++ b/ext/opus/gstopusenc.c @@ -218,11 +218,9 @@ static void gst_opus_enc_class_init (GstOpusEncClass * klass) { GObjectClass *gobject_class; - GstElementClass *gstelement_class; GstAudioEncoderClass *base_class; gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; base_class = (GstAudioEncoderClass *) klass; gobject_class->set_property = gst_opus_enc_set_property;