[FFmpeg-devel] [PATCH] avformat/assenc: honor ReadOrder

Michael Niedermayer michaelni at gmx.at
Sat Sep 13 21:35:25 CEST 2014


On Sat, Sep 13, 2014 at 09:06:56PM +0200, Clément Bœsch wrote:
> ---
>  libavformat/assenc.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 85 insertions(+), 4 deletions(-)
> 
> diff --git a/libavformat/assenc.c b/libavformat/assenc.c
> index 9fb9f23..acc21b9 100644
> --- a/libavformat/assenc.c
> +++ b/libavformat/assenc.c
> @@ -19,12 +19,22 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  
> +#include "libavutil/avstring.h"
>  #include "avformat.h"
>  #include "internal.h"
>  
> +typedef struct DialogueLine {
> +    int readorder;
> +    char *line;
> +    struct DialogueLine *prev, *next;
> +} DialogueLine;
> +
>  typedef struct ASSContext{
>      unsigned int extra_index;
>      int write_ts; // 0: ssa (timing in payload), 1: ass (matroska like)
> +    int expected_readorder;
> +    DialogueLine *dialogue_cache;
> +    int cache_size;
>  }ASSContext;
>  
>  static int write_header(AVFormatContext *s)
> @@ -60,19 +70,82 @@ static int write_header(AVFormatContext *s)
>      return 0;
>  }
>  
> +static void purge_dialogues(AVFormatContext *s, int force)
> +{
> +    int n = 0;
> +    ASSContext *ass = s->priv_data;
> +    DialogueLine *dialogue = ass->dialogue_cache;
> +
> +    while (dialogue && (dialogue->readorder == ass->expected_readorder || force)) {
> +        DialogueLine *next = dialogue->next;
> +        if (dialogue->readorder != ass->expected_readorder) {
> +            av_log(s, AV_LOG_WARNING, "ReadOrder gap found between %d and %d\n",
> +                   ass->expected_readorder, dialogue->readorder);
> +            ass->expected_readorder = dialogue->readorder;
> +        }
> +        avio_printf(s->pb, "Dialogue: %s\r\n", dialogue->line);
> +        av_free(dialogue->line);
> +        av_free(dialogue);
> +        if (next)
> +            next->prev = NULL;
> +        dialogue = ass->dialogue_cache = next;
> +        ass->expected_readorder++;
> +        n++;
> +    }
> +    ass->cache_size -= n;
> +    if (n > 1)
> +        av_log(s, AV_LOG_DEBUG, "wrote %d ASS lines, cached dialogues: %d, waiting for event id %d\n",
> +               n, ass->cache_size, ass->expected_readorder);
> +}
> +
> +static void insert_dialogue(ASSContext *ass, DialogueLine *dialogue)
> +{
> +    DialogueLine *cur, *next, *prev = NULL;
> +
> +    next = ass->dialogue_cache;
> +    for (cur = next; cur; cur = cur->next) {
> +        if (cur->readorder > dialogue->readorder)
> +            break;
> +        prev = cur;
> +        next = cur->next;
> +    }
> +    if (prev) {
> +        prev->next = dialogue;
> +        dialogue->prev = prev;
> +    } else {
> +        dialogue->prev = ass->dialogue_cache;
> +        ass->dialogue_cache = dialogue;
> +    }
> +    if (next) {
> +        next->prev = dialogue;
> +        dialogue->next = next;
> +    }
> +    ass->cache_size++;
> +}

iam not sure what the typical insert vs remove statistics are but
this looks like O(n^2) time to me, which might be a problem if there
are millions of entries

for a mixed insert + remove "lowest" data structure, theres heap
sort with O(n log n) worst case, or various other options


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

Democracy is the form of government in which you can choose your dictator
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140913/88fc900f/attachment.asc>


More information about the ffmpeg-devel mailing list