[FFmpeg-devel] [PATCH v4 2/3] aadec: add chapters and seeking

Michael Niedermayer michael at niedermayer.cc
Sun Jul 8 12:12:24 EEST 2018


On Sat, Jul 07, 2018 at 07:41:28PM +0200, Karsten Otto wrote:
> read_packet reads content in chunks. Thus seek must be clamped to valid
> chunk positions in the file, which in turn are relative to chapter start
> positions.
> 
> So in read_header, scan for chapter headers once by skipping through the
> content. Set stream time_base based on bitrate in bytes/s, for easy
> timestamp to position conversion.
> 
> Then in read_seek, find the chapter containing the seek position, calculate
> the nearest chunk position, and reinit the read_seek state accordingly.
> ---
>  libavformat/aadec.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 83 insertions(+), 4 deletions(-)
> 
> diff --git a/libavformat/aadec.c b/libavformat/aadec.c
> index 4db71b1939..e3c03bc522 100644
> --- a/libavformat/aadec.c
> +++ b/libavformat/aadec.c
> @@ -35,6 +35,8 @@
>  #define MAX_TOC_ENTRIES 16
>  #define MAX_DICTIONARY_ENTRIES 128
>  #define TEA_BLOCK_SIZE 8
> +#define CHAPTER_HEADER_SIZE 8
> +#define TIMEPREC 1000
>  
>  typedef struct AADemuxContext {
>      AVClass *class;
> @@ -46,6 +48,7 @@ typedef struct AADemuxContext {
>      struct AVTEA *tea_ctx;
>      uint8_t file_key[16];
>      int64_t current_chapter_size;
> +    int64_t content_start;
>      int64_t content_end;
>  } AADemuxContext;
>  
> @@ -70,7 +73,7 @@ static int aa_read_header(AVFormatContext *s)
>      uint32_t nkey, nval, toc_size, npairs, header_seed = 0, start;
>      char key[128], val[128], codec_name[64] = {0};
>      uint8_t output[24], dst[8], src[8];
> -    int64_t largest_size = -1, current_size = -1;
> +    int64_t largest_size = -1, current_size = -1, chapter_pos;
>      struct toc_entry {
>          uint32_t offset;
>          uint32_t size;
> @@ -173,19 +176,23 @@ static int aa_read_header(AVFormatContext *s)
>          st->codecpar->codec_id = AV_CODEC_ID_MP3;
>          st->codecpar->sample_rate = 22050;
>          st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
> -        st->start_time = 0;
> +        avpriv_set_pts_info(st, 64, 8, 32000 * TIMEPREC);
>      } else if (!strcmp(codec_name, "acelp85")) {
>          st->codecpar->codec_id = AV_CODEC_ID_SIPR;
>          st->codecpar->block_align = 19;
>          st->codecpar->channels = 1;
>          st->codecpar->sample_rate = 8500;
> +        st->codecpar->bit_rate = 8500;
>          st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
> +        avpriv_set_pts_info(st, 64, 8, 8500 * TIMEPREC);
>      } else if (!strcmp(codec_name, "acelp16")) {
>          st->codecpar->codec_id = AV_CODEC_ID_SIPR;
>          st->codecpar->block_align = 20;
>          st->codecpar->channels = 1;
>          st->codecpar->sample_rate = 16000;
> +        st->codecpar->bit_rate = 16000;
>          st->need_parsing = AVSTREAM_PARSE_FULL_RAW;
> +        avpriv_set_pts_info(st, 64, 8, 16000 * TIMEPREC);
>      }
>  
>      /* determine, and jump to audio start offset */
> @@ -198,7 +205,30 @@ static int aa_read_header(AVFormatContext *s)
>      }
>      start = TOC[largest_idx].offset;
>      avio_seek(pb, start, SEEK_SET);
> +
> +    // extract chapter positions. since all formats have constant bit rate, use it
> +    // as time base in bytes/s, for easy stream position <-> timestamp conversion
> +    st->start_time = 0;
> +    c->content_start = start;
>      c->content_end = start + largest_size;
> +

> +    while ((chapter_pos = avio_tell(pb)) >= 0 && chapter_pos < c->content_end) {
> +        int chapter_idx, chapter_size;
> +        chapter_idx = s->nb_chapters;
> +        chapter_pos -= start + CHAPTER_HEADER_SIZE * chapter_idx;
> +        chapter_size = avio_rb32(pb);
> +        if (chapter_size == 0) break;
> +        avio_skip(pb, 4);
> +        avio_skip(pb, chapter_size);

I think this can end in an infinite loop if chapter_size is negative

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Many that live deserve death. And some that die deserve life. Can you give
it to them? Then do not be too eager to deal out death in judgement. For
even the very wise cannot see all ends. -- Gandalf
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20180708/15b7d073/attachment.sig>


More information about the ffmpeg-devel mailing list