diff mbox

[FFmpeg-devel,v4,1/2] avformat/mpegts: opus muxing for mapping family 255

Message ID 2461eb3e-d3ba-7d7f-e02c-69d704deb187@gmail.com
State Superseded
Headers show

Commit Message

pkv.stream Oct. 28, 2017, 1:49 a.m. UTC
From 105f20b8af8ce5376165ca30a81276dae2e61e40 Mon Sep 17 00:00:00 2001
From: pkviet <pkv.stream@gmail.com>
Date: Sat, 28 Oct 2017 02:48:08 +0200
Subject: [PATCH 1/2] libavf/mpegts: opus muxing for mapping family 255

Adds to mpegts muxer the capability  to mux libopus with mapping family
255, following the provisional spec for opus in mepg-ts
(https://people.xiph.org/~tterribe/opus/ETSI_TS_opus-v0.1.3-draft.doc).

Signed-off-by: pkviet <pkv.stream@gmail.com>
---
 libavformat/mpegtsenc.c | 67 +++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 60 insertions(+), 7 deletions(-)

Comments

Michael Niedermayer Oct. 29, 2017, 3:44 p.m. UTC | #1
On Sat, Oct 28, 2017 at 03:49:13AM +0200, pkv.stream wrote:
> 
> 

>  mpegtsenc.c |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 60 insertions(+), 7 deletions(-)
> 1423a193788547952e3c4cdcb424b4724b0f1157  0001-libavf-mpegts-opus-muxing-for-mapping-family-255.patch
> From 105f20b8af8ce5376165ca30a81276dae2e61e40 Mon Sep 17 00:00:00 2001
> From: pkviet <pkv.stream@gmail.com>
> Date: Sat, 28 Oct 2017 02:48:08 +0200
> Subject: [PATCH 1/2] libavf/mpegts: opus muxing for mapping family 255
> 
> Adds to mpegts muxer the capability  to mux libopus with mapping family
> 255, following the provisional spec for opus in mepg-ts
> (https://people.xiph.org/~tterribe/opus/ETSI_TS_opus-v0.1.3-draft.doc).
> 
> Signed-off-by: pkviet <pkv.stream@gmail.com>
> ---
>  libavformat/mpegtsenc.c | 67 +++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 60 insertions(+), 7 deletions(-)
> 
> diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
> index fdfa544..a31663c 100644
> --- a/libavformat/mpegtsenc.c
> +++ b/libavformat/mpegtsenc.c
> @@ -28,6 +28,7 @@
>  #include "libavutil/opt.h"
>  
>  #include "libavcodec/internal.h"
> +#include "libavcodec/put_bits.h"
>  
>  #include "avformat.h"
>  #include "avio_internal.h"
> @@ -291,6 +292,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
>      MpegTSWrite *ts = s->priv_data;
>      uint8_t data[SECTION_LENGTH], *q, *desc_length_ptr, *program_info_length_ptr;
>      int val, stream_type, i, err = 0;
> +    uint8_t channel_count, stream_count, coupled_stream_count, *buf;
> +    PutBitContext pbc;
> +    size_t buf_size;
>  
>      q = data;
>      put16(&q, 0xe000 | service->pcr_pid);
> @@ -421,8 +425,8 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
>                  *q++ = 'D';
>              }
>              if (st->codecpar->codec_id==AV_CODEC_ID_OPUS) {
> -                /* 6 bytes registration descriptor, 4 bytes Opus audio descriptor */
> -                if (q - data > SECTION_LENGTH - 6 - 4) {
> +                /* 6 bytes registration descriptor, 6 bytes Opus audio descriptor */
> +                if (q - data > SECTION_LENGTH - 6 - 6) {
>                      err = 1;
>                      break;
>                  }
> @@ -435,8 +439,19 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
>                  *q++ = 's';
>  
>                  *q++ = 0x7f; /* DVB extension descriptor */
> -                *q++ = 2;
> -                *q++ = 0x80;
> +                /* descriptor_length */
> +                if (st->codecpar->extradata[18] == 255) {
> +                    /* dual mono */
> +                    if (st->codecpar->channels == 2) {
> +                        *q++ = 2;
> +                    } else {
> +                    /* channel_config_code 0x81 */
> +                        *q++ = st->codecpar->channels + 6;
> +                    }
> +                } else {
> +                    *q++ = 2;
> +                }
> +                *q++ = 0x80; /* descriptor_tag_extension */
>  
>                  if (st->codecpar->extradata && st->codecpar->extradata_size >= 19) {
>                      if (st->codecpar->extradata[18] == 0 && st->codecpar->channels <= 2) {
> @@ -483,9 +498,47 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
>                              *q++ = 0xff;
>                          }
>                      } else {
> -                        /* Unsupported */
> -                        av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]);
> -                        *q++ = 0xff;
> +                        /* mapping family 255 , set channel_config_code to 0x81 except for dual-mono */
> +                        if (st->codecpar->extradata[18] == 255) {
> +                            /* dual mono */
> +                            if (st->codecpar->channels == 2 && st->codecpar->extradata[19] == 1) {
> +                                *q++ = 0x00;
> +                            } else if (st->codecpar->channels == 2 && st->codecpar->extradata[19] == 2) {
> +                                *q++ = 0x80;
> +                            } else {
> +                            /* application defined channel configuration */
> +                                *q++ = 0x81;
> +                                *q++ = st->codecpar->channels;
> +                                *q++ = st->codecpar->extradata[18];
> +                                channel_count = st->codecpar->channels;
> +                                stream_count = st->codecpar->extradata[19];
> +                                coupled_stream_count = st->codecpar->extradata[20];
> +                                buf = av_mallocz_array( st->codecpar->channels + 2 , sizeof(uint8_t));

> +                                if (!buf) {
> +                                        av_freep(buf);

that looks wrong


> +                                        return AVERROR(ENOMEM);
> +                                }
> +                                init_put_bits(&pbc, buf, (st->codecpar->channels + 2));
> +                                put_bits(&pbc, av_ceil_log2_c(channel_count), st->codecpar->extradata[19] - 1);
> +                                put_bits(&pbc, av_ceil_log2_c(stream_count + 1), st->codecpar->extradata[20]);
> +                                for (i = 0; i < channel_count; i++) {
> +                                    put_bits(&pbc, av_ceil_log2_c(stream_count + coupled_stream_count + 1), st->codecpar->extradata[21 + i]);
> +                                }
> +                                flush_put_bits(&pbc);
> +                                buf_size = av_ceil_log2_c(channel_count) + av_ceil_log2_c(stream_count + 1)
> +                                       + channel_count * (av_ceil_log2_c(stream_count + coupled_stream_count + 1))
> +                                       + (8 * (2 + channel_count) - av_ceil_log2_c(channel_count) - av_ceil_log2_c(stream_count + 1)
> +                                       - channel_count * (av_ceil_log2_c(stream_count + coupled_stream_count + 1))) % 8;

this duplicates previious expressions
also it can probably  be simplified with put_bits_count()


> +                                for (i = 0; i < buf_size; i++) {

> +                                    memcpy(q++, buf+i, 1);

memcpy isnt needed for seting one char

thx

[...]
diff mbox

Patch

diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c
index fdfa544..a31663c 100644
--- a/libavformat/mpegtsenc.c
+++ b/libavformat/mpegtsenc.c
@@ -28,6 +28,7 @@ 
 #include "libavutil/opt.h"
 
 #include "libavcodec/internal.h"
+#include "libavcodec/put_bits.h"
 
 #include "avformat.h"
 #include "avio_internal.h"
@@ -291,6 +292,9 @@  static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
     MpegTSWrite *ts = s->priv_data;
     uint8_t data[SECTION_LENGTH], *q, *desc_length_ptr, *program_info_length_ptr;
     int val, stream_type, i, err = 0;
+    uint8_t channel_count, stream_count, coupled_stream_count, *buf;
+    PutBitContext pbc;
+    size_t buf_size;
 
     q = data;
     put16(&q, 0xe000 | service->pcr_pid);
@@ -421,8 +425,8 @@  static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                 *q++ = 'D';
             }
             if (st->codecpar->codec_id==AV_CODEC_ID_OPUS) {
-                /* 6 bytes registration descriptor, 4 bytes Opus audio descriptor */
-                if (q - data > SECTION_LENGTH - 6 - 4) {
+                /* 6 bytes registration descriptor, 6 bytes Opus audio descriptor */
+                if (q - data > SECTION_LENGTH - 6 - 6) {
                     err = 1;
                     break;
                 }
@@ -435,8 +439,19 @@  static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                 *q++ = 's';
 
                 *q++ = 0x7f; /* DVB extension descriptor */
-                *q++ = 2;
-                *q++ = 0x80;
+                /* descriptor_length */
+                if (st->codecpar->extradata[18] == 255) {
+                    /* dual mono */
+                    if (st->codecpar->channels == 2) {
+                        *q++ = 2;
+                    } else {
+                    /* channel_config_code 0x81 */
+                        *q++ = st->codecpar->channels + 6;
+                    }
+                } else {
+                    *q++ = 2;
+                }
+                *q++ = 0x80; /* descriptor_tag_extension */
 
                 if (st->codecpar->extradata && st->codecpar->extradata_size >= 19) {
                     if (st->codecpar->extradata[18] == 0 && st->codecpar->channels <= 2) {
@@ -483,9 +498,47 @@  static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service)
                             *q++ = 0xff;
                         }
                     } else {
-                        /* Unsupported */
-                        av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]);
-                        *q++ = 0xff;
+                        /* mapping family 255 , set channel_config_code to 0x81 except for dual-mono */
+                        if (st->codecpar->extradata[18] == 255) {
+                            /* dual mono */
+                            if (st->codecpar->channels == 2 && st->codecpar->extradata[19] == 1) {
+                                *q++ = 0x00;
+                            } else if (st->codecpar->channels == 2 && st->codecpar->extradata[19] == 2) {
+                                *q++ = 0x80;
+                            } else {
+                            /* application defined channel configuration */
+                                *q++ = 0x81;
+                                *q++ = st->codecpar->channels;
+                                *q++ = st->codecpar->extradata[18];
+                                channel_count = st->codecpar->channels;
+                                stream_count = st->codecpar->extradata[19];
+                                coupled_stream_count = st->codecpar->extradata[20];
+                                buf = av_mallocz_array( st->codecpar->channels + 2 , sizeof(uint8_t));
+                                if (!buf) {
+                                        av_freep(buf);
+                                        return AVERROR(ENOMEM);
+                                }
+                                init_put_bits(&pbc, buf, (st->codecpar->channels + 2));
+                                put_bits(&pbc, av_ceil_log2_c(channel_count), st->codecpar->extradata[19] - 1);
+                                put_bits(&pbc, av_ceil_log2_c(stream_count + 1), st->codecpar->extradata[20]);
+                                for (i = 0; i < channel_count; i++) {
+                                    put_bits(&pbc, av_ceil_log2_c(stream_count + coupled_stream_count + 1), st->codecpar->extradata[21 + i]);
+                                }
+                                flush_put_bits(&pbc);
+                                buf_size = av_ceil_log2_c(channel_count) + av_ceil_log2_c(stream_count + 1)
+                                       + channel_count * (av_ceil_log2_c(stream_count + coupled_stream_count + 1))
+                                       + (8 * (2 + channel_count) - av_ceil_log2_c(channel_count) - av_ceil_log2_c(stream_count + 1)
+                                       - channel_count * (av_ceil_log2_c(stream_count + coupled_stream_count + 1))) % 8;
+                                for (i = 0; i < buf_size; i++) {
+                                    memcpy(q++, buf+i, 1);
+                                }
+                                av_freep(&buf);
+                            }
+                        } else {
+                            /* Unsupported */
+                            av_log(s, AV_LOG_ERROR, "Unsupported Opus channel mapping for family %d", st->codecpar->extradata[18]);
+                            *q++ = 0xff;
+                        }
                     }
                 } else if (st->codecpar->channels <= 2) {
                     /* Assume RTP mapping family */