On Sun, 27 Jul 2014 01:23:34 +0100, Kieran Kunhya <[email protected]> wrote:
> ---
>  libavcodec/opus.c        |   11 +---
>  libavcodec/opus.h        |    9 +++
>  libavcodec/opus_parser.c |  139 
> +++++++++++++++++++++++++++++++++++++++++-----
>  libavcodec/opusdec.c     |    1 +
>  libavformat/mpegts.c     |   54 +++++++++++++++++-
>  5 files changed, 192 insertions(+), 22 deletions(-)
> 
> diff --git a/libavcodec/opus.c b/libavcodec/opus.c
> index 91021ce..1bc417b 100644
> --- a/libavcodec/opus.c
> +++ b/libavcodec/opus.c
> @@ -290,10 +290,6 @@ av_cold int ff_opus_parse_extradata(AVCodecContext 
> *avctx,
>                                      OpusContext *s)
>  {
>      static const uint8_t default_channel_map[2] = { 0, 1 };
> -    uint8_t default_extradata[19] = {
> -        'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
> -        1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> -    };
>  
>      int (*channel_reorder)(int, int) = channel_reorder_unknown;
>  
> @@ -308,9 +304,8 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
>                     "Multichannel configuration without extradata.\n");
>              return AVERROR(EINVAL);
>          }
> -        default_extradata[9] = (avctx->channels == 1) ? 1 : 2;
> -        extradata      = default_extradata;
> -        extradata_size = sizeof(default_extradata);
> +        extradata      = opus_default_extradata;
> +        extradata_size = sizeof(opus_default_extradata);
>      } else {
>          extradata = avctx->extradata;
>          extradata_size = avctx->extradata_size;
> @@ -330,7 +325,7 @@ av_cold int ff_opus_parse_extradata(AVCodecContext *avctx,
>  
>      avctx->delay = AV_RL16(extradata + 10);
>  
> -    channels = extradata[9];
> +    channels = avctx->extradata ? extradata[9] : (avctx->channels == 1) ? 1 
> : 2;
>      if (!channels) {
>          av_log(avctx, AV_LOG_ERROR, "Zero channel count specified in the 
> extadata\n");
>          return AVERROR_INVALIDDATA;
> diff --git a/libavcodec/opus.h b/libavcodec/opus.h
> index c2fac06..94993d6 100644
> --- a/libavcodec/opus.h
> +++ b/libavcodec/opus.h
> @@ -61,6 +61,15 @@
>  #define ROUND_MUL16(a,b)  ((MUL16(a, b) + 16384) >> 15)
>  #define opus_ilog(i) (av_log2(i) + !!(i))
>  
> +#define OPUS_TS_HEADER     0x7FE0        // 0x3ff (11 bits)
> +#define OPUS_TS_MASK       0xFFE0        // top 11 bits
> +
> +static const uint8_t opus_default_extradata[30] = {
> +    'O', 'p', 'u', 's', 'H', 'e', 'a', 'd',
> +    1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> +    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
> +};
> +
>  enum OpusMode {
>      OPUS_MODE_SILK,
>      OPUS_MODE_HYBRID,
> diff --git a/libavcodec/opus_parser.c b/libavcodec/opus_parser.c
> index 8a2bc22..d218c81 100644
> --- a/libavcodec/opus_parser.c
> +++ b/libavcodec/opus_parser.c
> @@ -27,49 +27,162 @@
>  
>  #include "avcodec.h"
>  #include "opus.h"
> +#include "parser.h"
> +#include "bytestream.h"
>  
>  typedef struct OpusParseContext {
>      OpusContext ctx;
>      OpusPacket pkt;
>      int extradata_parsed;
> +    ParseContext pc;
> +    int ts_framing;
>  } OpusParseContext;
>  
> -static int opus_parse(AVCodecParserContext *ctx, AVCodecContext *avctx,
> -                      const uint8_t **poutbuf, int *poutbuf_size,
> -                      const uint8_t *buf, int buf_size)
> +static uint8_t *ff_parse_opus_ts_header(const uint8_t *start, int 
> *payload_len, int buf_len)

Drop the ff_

> +{
> +    uint8_t *buf = start + 1;
> +    int start_trim_flag, end_trim_flag, control_extension_flag, 
> control_extension_length, i;
> +
> +    start_trim_flag        = (buf[0] >> 4) & 1;
> +    end_trim_flag          = (buf[0] >> 3) & 1;
> +    control_extension_flag = (buf[0] >> 2) & 1;
> +    buf++;

This silently assumes buf_len is at least 3.
I think using the bytestream2 API would make this simpler.

> +
> +    *payload_len = 0;
> +    while (buf[0] == 0xff && buf - start <= buf_len) {
> +        *payload_len += buf[0];
> +        buf++;
> +    }
> +    *payload_len += buf[0];
> +    buf++;
> +
> +    if (start_trim_flag)
> +        buf += 2;
> +    if (end_trim_flag)
> +        buf += 2;
> +    if (control_extension_flag && buf - start <= buf_len) {
> +        control_extension_length = *buf++;
> +        for (i = 0; i < control_extension_length && buf - start <= buf_len; 
> i++)
> +             buf++;
> +    }
> +
> +    return buf;
> +}
> +
> +/**
> + * Find the end of the current frame in the bitstream.
> + * @return the position of the first byte of the next frame, or -1
> + */
> +static int opus_find_frame_end(AVCodecParserContext *ctx, AVCodecContext 
> *avctx,
> +                               const uint8_t *buf, int buf_size, int 
> *header_len)
>  {
>      OpusParseContext *s = ctx->priv_data;
> -    int ret;
> +    ParseContext *pc    = &s->pc;
> +    int ret, start_found, i = 0, payload_len = 0;
> +    uint8_t *payload;
> +    uint32_t state;
> +    uint16_t hdr;
> +    *header_len = 0;
>  
>      if (!buf_size)
>          return 0;
>  
> +    start_found = pc->frame_start_found;
> +    state = pc->state;
> +    payload = buf;
> +
> +    /* Check if we're using Opus in MPEG-TS framing */
> +    if (!s->ts_framing & buf_size > 2) {
                          ^
Missing a &?

> +        hdr = AV_RB16(buf);
> +        if ((hdr & OPUS_TS_MASK) == OPUS_TS_HEADER)
> +            s->ts_framing = 1;
> +    }
> +
> +    if (s->ts_framing && !start_found) {
> +        for (i = 0; i < buf_size-2; i++) {
> +            state = (state << 8) | payload[i];
> +            if ((state & OPUS_TS_MASK) == OPUS_TS_HEADER) {
> +                payload = ff_parse_opus_ts_header(payload, &payload_len, 
> buf_size - i);
> +                *header_len = payload - buf;
> +                start_found = 1;
> +                break;
> +            }
> +        }
> +    }
> +
> +    if (!s->ts_framing)
> +        payload_len = buf_size;
> +
>      if (avctx->extradata && !s->extradata_parsed) {
>          ret = ff_opus_parse_extradata(avctx, &s->ctx);
>          if (ret < 0) {
>              av_log(avctx, AV_LOG_ERROR, "Error parsing Ogg extradata.\n");
> -            goto fail;
> +            return AVERROR_INVALIDDATA;
>          }
>          av_freep(&s->ctx.channel_maps);
>          s->extradata_parsed = 1;
>      }
>  
> -    ret = ff_opus_parse_packet(&s->pkt, buf, buf_size, s->ctx.nb_streams > 
> 1);
> -    if (ret < 0) {
> -        av_log(avctx, AV_LOG_ERROR, "Error parsing Opus packet header.\n");
> -        goto fail;
> +    if (payload_len <= buf_size && (!s->ts_framing || start_found)) {
> +        s->ctx.nb_streams = 1;

Eh? Doesn't this break multichannel?

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to