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