<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Dec 9, 2013 at 2:55 PM, Taha Ansari <span dir="ltr"><<a href="mailto:mtaha.ansari@gmail.com" target="_blank">mtaha.ansari@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div><div><div><div><div><div>Hi all!<br><br></div>I am writing a small test program that will convert .SRT subtitle file to .ASS format.<br>
<br>original SRT file (subtitle.srt):<br><br>1<br>00:00:02,000 --> 00:00:06,000<br>
Hello<br><br>2<br>00:00:15,000 --> 00:00:20,000<br>World<br><br>3<br>00:01:00,000 --> 00:01:10,000<br>!!Again!!<br><br></div>Demo code:<br><br>#include "stdafx.h"<br><br>//using namespace std;<br><br>#include <iostream><br>

#include <fstream><br><br>#include <string><br>#include <vector><br>#include <map><br>//#include <DShow.h><br>#include <conio.h><br><br>#include <deque><br>#include <queue><br>

<br>#include <math.h><br>#include <stdlib.h><br>#include <stdio.h><br>#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000<br>extern "C"<br>{<br>#include "libavcodec/avcodec.h"<br>#include "libavformat/avformat.h"<br>

#include "libavdevice/avdevice.h"<br>#include "libswscale/swscale.h"<br>#include "libavutil/dict.h"<br>#include "libavutil/error.h"<br>#include "libavutil/opt.h"<br>#include <libavutil/fifo.h><br>

#include <libavutil/imgutils.h><br>#include <libavutil/samplefmt.h><br>#include <libavutil/time.h><br>#include <libavformat/avio.h><br>#include <libavutil/avstring.h><br>#include <libavutil/mathematics.h><br>

#include "libavfilter/avfiltergraph.h"<br>#include "libavfilter/avcodec.h"<br>#include "libavfilter/buffersink.h"<br>#include "libavfilter/buffersrc.h"<br><br>#include <libswresample/swresample.h><br>

}<br><br>//++decoder++//<br>AVFormatContext    *pFormatCtx = 0;<br>int                subtitleIndex = -1;<br>AVPacket        packet;<br>AVCodecContext    *pCodecCtxSubtitle = 0;<br>AVCodec            *pCodecSubtitle = 0;<br>

AVSubtitle        subtitle;<br>//--decoder--<br><br>//++encoder++<br>AVFormatContext    *pOutputFormatCtx=0;<br>AVStream        *subtitle_st=0;<br>AVOutputFormat    *outputFmt=0;<br>AVCodec            *subtitle_codec=0;<br>

/* Add an output stream. */<br>AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,<br>    enum AVCodecID codec_id)<br>{<br>    AVCodecContext *c;<br>    AVStream *st;<br><br>    /* find the encoder */<br>    *codec = avcodec_find_encoder(codec_id);<br>

    if (!(*codec)) {<br>        fprintf(stderr, "Could not find encoder for '%s'\n",<br>            avcodec_get_name(codec_id));<br>        exit(1);<br>    }<br><br>    st = avformat_new_stream(oc, *codec);<br>

    if (!st) {<br>        fprintf(stderr, "Could not allocate stream\n");<br>        exit(1);<br>    }<br>    st->id = oc->nb_streams-1;<br>    c = st->codec;<br><br>    avcodec_get_context_defaults3( c, *codec);<br>

<br>    switch ((*codec)->type) <br>    {<br>    case AVMEDIA_TYPE_SUBTITLE:<br>        break;<br>    default:<br>        break;<br>    }<br><br>    /* Some formats want stream headers to be separate. */<br>    if (oc->oformat->flags & AVFMT_GLOBALHEADER)<br>

        c->flags |= CODEC_FLAG_GLOBAL_HEADER;<br><br>    return st;<br>}<br><br>void open_subtitle(AVFormatContext *oc, AVCodec *codec, AVStream *st)<br>{<br>    int ret;<br>    AVCodecContext *c = st->codec;<br><br>

    /* open the codec */<br>    ret = avcodec_open2(c, codec, NULL);<br>    if (ret < 0) <br>    {<br>        exit(1);<br>    }<br>}<br>//--encoder--<br><br>int main (int argc, char **argv)<br>{<br>    av_register_all();<br>

    avcodec_register_all();<br>    avfilter_register_all();<br><br>    char inputFilename[90]="subtitle.srt";<br>    char outputFilename[90]="temp.ass";<br>    int rv = 0;<br><br>    // ++decoder++<br>

    int got_subtitle = 0;<br>    pFormatCtx = avformat_alloc_context();<br><br>    rv = avformat_open_input(&pFormatCtx, inputFilename, NULL, NULL);<br><br>    for(int i=0; i < pFormatCtx->nb_streams; i++)<br>    {<br>

        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_SUBTITLE) <br>        {<br>            subtitleIndex = i;<br>        }<br>    }<br>    if ( subtitleIndex >= 0 )<br>    {<br>        pCodecCtxSubtitle=pFormatCtx->streams[subtitleIndex]->codec;<br>

<br>        pCodecSubtitle = avcodec_find_decoder(pCodecCtxSubtitle->codec_id);<br>        if(pCodecSubtitle==NULL) <br>        {<br>            return -1; // Codec not found<br>        }<br>        // Open codec<br>        AVDictionary *codecDictOptions = NULL;<br>

        if(avcodec_open2(pCodecCtxSubtitle, pCodecSubtitle, &codecDictOptions) < 0 )//error<br>        {<br>        }<br>    }<br>    //--decoder--<br><br>    //++encoder++<br>    int ret;<br>    avformat_alloc_output_context2(&pOutputFormatCtx, NULL, NULL, outputFilename);<br>

    if (!pOutputFormatCtx) <br>    {<br>        rv = 1;<br>    }<br>    //outputFmt = pOutputFormatCtx->oformat;<br>    outputFmt = av_guess_format( NULL, outputFilename, NULL );<br>    if (outputFmt->subtitle_codec != AV_CODEC_ID_NONE) <br>

    {<br>        subtitle_st = add_stream(pOutputFormatCtx, &subtitle_codec, outputFmt->subtitle_codec);<br>    }<br><br>    if (subtitle_st)<br>        open_subtitle(pOutputFormatCtx, subtitle_codec, subtitle_st);<br>

<br>    av_dump_format(pOutputFormatCtx, 0, outputFilename, 1);<br>    /* open the output file, if needed */<br>    if (!(outputFmt->flags & AVFMT_NOFILE)) <br>    {<br>        if (avio_open(&pOutputFormatCtx->pb, outputFilename, AVIO_FLAG_WRITE) < 0) <br>

        {<br>            rv = 1;<br>        }<br>        else<br>        {<br>            /* Write the stream header, if any. */<br>            if (avformat_write_header(pOutputFormatCtx, NULL) < 0) <br>            {<br>

                rv = 1;<br>            }<br>        }<br>    }<br><br>    AVCodecContext *c = subtitle_st->codec;<br>    //--encoder--<br><br>    while( av_read_frame( pFormatCtx, &packet ) >= 0 )<br>    {<br>        if(packet.stream_index != subtitle_st->index)<br>

            continue;<br>        int gotSubtitle = 0;<br>        rv = avcodec_decode_subtitle2( pCodecCtxSubtitle, &subtitle, &gotSubtitle, &packet );<br>        uint64_t bufferSize = 1024 * 1024 ;<br>        uint8_t *buffer = new uint8_t[bufferSize];<br>

        memset(buffer, 0, bufferSize);<br>        if( rv >= 0 )<br>        {<br>            rv = avcodec_encode_subtitle( subtitle_st->codec, buffer, bufferSize, &subtitle );<br>            if ( rv >= 0 )<br>

            {<br>                AVPacket outPacket;<br>                av_init_packet(&outPacket);<br>                outPacket.data = buffer;<br>                outPacket.size = strlen((const char*)buffer);<br>                rv = av_interleaved_write_frame(pOutputFormatCtx, &outPacket);<br>

                av_free_packet(&outPacket);<br>            }<br>        }<br>        delete [] buffer;<br>    }<br><br>    if ( pCodecCtxSubtitle)        <br>    {<br>        avcodec_close(pCodecCtxSubtitle);<br>        pCodecCtxSubtitle= NULL;<br>

    }<br>    if ( pCodecSubtitle )            <br>    {<br>        av_free(pCodecSubtitle);<br>        pCodecSubtitle= NULL;<br>    }<br>    if ( pFormatCtx )<br>    {<br>        avformat_close_input(&pFormatCtx);<br>

        avformat_free_context(pFormatCtx);<br>        pFormatCtx = NULL;<br>    }<br>    avcodec_close(subtitle_st->codec);<br>    return rv;<br>}<br><br></div>PTS values are not calculated still, it is work in progress; but the above code gives me this output:<br>

<br></div>output temp.ass file:<br><br>Dialogue: 0,0:00:00.00,0:00:00.00,Default,Hello<br>Dialogue: 0,0:00:00.00,0:00:00.00,Default,World<br>Dialogue: 0,0:00:00.00,0:00:00.00,Default,!!Again!!<br><br></div>It is clearly missing all header information.<br>

<br>When i run ffmpeg command line to convert orignal SRT file using:<br><br>ffmpeg -i subtitle.srt temp.ass<br><br></div>I get:<br><br>[Script Info]<br>ScriptType: v4.00+<br><br>[V4+ Styles]<br>Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding<br>

Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,1,1,0,2,10,10,10,0,0<br><br>[Events]<br>Format: Layer, Start, End, Style, Text<br>Dialogue: 0,0:00:02.00,0:00:06.00,Default,Hello<br>Dialogue: 0,0:00:15.00,0:00:20.00,Default,World<br>

Dialogue: 0,0:01:00.00,0:01:10.00,Default,!!Again!!<br><br></div>so my question is, even though I am calling avformat_write_header() function, why isn't this header information being written through my code?<br><br></div>

Thanks in advance...<br></div>
</blockquote></div><br><div><div>Perhaps some code was missing in my original email, which I have added:<br><br>    if (pCodecCtxSubtitle && pCodecCtxSubtitle->subtitle_header) <br>    {<br>        /* ASS code assumes this buffer is null terminated so add extra byte. */<br>
        subtitle_st->codec->subtitle_header = (uint8_t*) av_mallocz(pCodecCtxSubtitle->subtitle_header_size + 1);<br>        if (!subtitle_st->codec->subtitle_header)<br>        {<br>            ret = AVERROR(ENOMEM);<br>
            //goto dump_format;<br>        }<br>   
     memcpy(subtitle_st->codec->subtitle_header, 
pCodecCtxSubtitle->subtitle_header, 
pCodecCtxSubtitle->subtitle_header_size);<br>        subtitle_st->codec->subtitle_header_size = pCodecCtxSubtitle->subtitle_header_size;<br>    }<br><br></div>So, final code now looks like this:<br><br><br>#include "stdafx.h"<br>
<br>//using namespace std;<br><br>#include <iostream><br>#include <fstream><br><br>#include <string><br>#include <vector><br>#include <map><br>//#include <DShow.h><br>#include <conio.h><br>
<br>#include <deque><br>#include <queue><br><br>#include <math.h><br>#include <stdlib.h><br>#include <stdio.h><br>#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000<br>extern "C"<br>{<br>#include "libavcodec/avcodec.h"<br>
#include "libavformat/avformat.h"<br>#include "libavdevice/avdevice.h"<br>#include "libswscale/swscale.h"<br>#include "libavutil/dict.h"<br>#include "libavutil/error.h"<br>
#include "libavutil/opt.h"<br>#include <libavutil/fifo.h><br>#include <libavutil/imgutils.h><br>#include <libavutil/samplefmt.h><br>#include <libavutil/time.h><br>#include <libavformat/avio.h><br>
#include <libavutil/avstring.h><br>#include <libavutil/mathematics.h><br>#include "libavfilter/avfiltergraph.h"<br>#include "libavfilter/avcodec.h"<br>#include "libavfilter/buffersink.h"<br>
#include "libavfilter/buffersrc.h"<br><br>#include <libswresample/swresample.h><br>}<br><br>//++decoder++//<br>AVFormatContext    *pFormatCtx = 0;<br>int                subtitleIndex = -1;<br>AVPacket        packet;<br>
AVCodecContext    *pCodecCtxSubtitle = 0;<br>AVCodec            *pCodecSubtitle = 0;<br>AVSubtitle        subtitle;<br>//--decoder--<br><br>//++encoder++<br>AVFormatContext    *pOutputFormatCtx=0;<br>AVStream        *subtitle_st=0;<br>
AVOutputFormat    *outputFmt=0;<br>AVCodec            *subtitle_codec=0;<br>/* Add an output stream. */<br>AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,<br>    enum AVCodecID codec_id)<br>{<br>    AVCodecContext *c;<br>
    AVStream *st;<br><br>    /* find the encoder */<br>    *codec = avcodec_find_encoder(codec_id);<br>    if (!(*codec)) {<br>        fprintf(stderr, "Could not find encoder for '%s'\n",<br>            avcodec_get_name(codec_id));<br>
        exit(1);<br>    }<br><br>    st = avformat_new_stream(oc, *codec);<br>    if (!st) {<br>        fprintf(stderr, "Could not allocate stream\n");<br>        exit(1);<br>    }<br>    st->id = oc->nb_streams-1;<br>
    c = st->codec;<br><br>    avcodec_get_context_defaults3( c, *codec);<br><br>    switch ((*codec)->type) <br>    {<br>    case AVMEDIA_TYPE_SUBTITLE:<br>        break;<br>    default:<br>        break;<br>    }<br>
<br>    /* Some formats want stream headers to be separate. */<br>    if (oc->oformat->flags & AVFMT_GLOBALHEADER)<br>        c->flags |= CODEC_FLAG_GLOBAL_HEADER;<br><br>    return st;<br>}<br><br>void open_subtitle(AVFormatContext *oc, AVCodec *codec, AVStream *st)<br>
{<br>    int ret;<br>    AVCodecContext *c = st->codec;<br><br>    /* open the codec */<br>    ret = avcodec_open2(c, codec, NULL);<br>    if (ret < 0) <br>    {<br>        exit(1);<br>    }<br>}<br>//--encoder--<br>
<br>int main (int argc, char **argv)<br>{<br>    av_register_all();<br>    avcodec_register_all();<br>    avfilter_register_all();<br><br>    char inputFilename[90]="subtitle.srt";<br>    char outputFilename[90]="temp.ass";<br>
    int rv = 0;<br><br>    // ++decoder++<br>    int got_subtitle = 0;<br>    pFormatCtx = avformat_alloc_context();<br><br>    rv = avformat_open_input(&pFormatCtx, inputFilename, NULL, NULL);<br><br>    for(int i=0; i < pFormatCtx->nb_streams; i++)<br>
    {<br>        if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_SUBTITLE) <br>        {<br>            subtitleIndex = i;<br>        }<br>    }<br>    if ( subtitleIndex >= 0 )<br>    {<br>        pCodecCtxSubtitle=pFormatCtx->streams[subtitleIndex]->codec;<br>
<br>        pCodecSubtitle = avcodec_find_decoder(pCodecCtxSubtitle->codec_id);<br>        if(pCodecSubtitle==NULL) <br>        {<br>            return -1; // Codec not found<br>        }<br>        // Open codec<br>        AVDictionary *codecDictOptions = NULL;<br>
        if(avcodec_open2(pCodecCtxSubtitle, pCodecSubtitle, &codecDictOptions) < 0 )//error<br>        {<br>        }<br>    }<br>    //--decoder--<br><br>    //++encoder++<br>    int ret;<br>    avformat_alloc_output_context2(&pOutputFormatCtx, NULL, NULL, outputFilename);<br>
    if (!pOutputFormatCtx) <br>    {<br>        rv = 1;<br>    }<br>    //outputFmt = pOutputFormatCtx->oformat;<br>    outputFmt = av_guess_format( NULL, outputFilename, NULL );<br>    if (outputFmt->subtitle_codec != AV_CODEC_ID_NONE) <br>
    {<br>        subtitle_st = add_stream(pOutputFormatCtx, &subtitle_codec, outputFmt->subtitle_codec);<br>    }<br><br>    if (subtitle_st)<br>        open_subtitle(pOutputFormatCtx, subtitle_codec, subtitle_st);<br>
    if (pCodecCtxSubtitle && pCodecCtxSubtitle->subtitle_header) <br>    {<br>        /* ASS code assumes this buffer is null terminated so add extra byte. */<br>        subtitle_st->codec->subtitle_header = (uint8_t*) av_mallocz(pCodecCtxSubtitle->subtitle_header_size + 1);<br>
        if (!subtitle_st->codec->subtitle_header)<br>        {<br>            ret = AVERROR(ENOMEM);<br>            //goto dump_format;<br>        }<br>   
     memcpy(subtitle_st->codec->subtitle_header, 
pCodecCtxSubtitle->subtitle_header, 
pCodecCtxSubtitle->subtitle_header_size);<br>        subtitle_st->codec->subtitle_header_size = pCodecCtxSubtitle->subtitle_header_size;<br>    }<br><br>    av_dump_format(pOutputFormatCtx, 0, outputFilename, 1);<br>
    /* open the output file, if needed */<br>    if (!(outputFmt->flags & AVFMT_NOFILE)) <br>    {<br>        if (avio_open(&pOutputFormatCtx->pb, outputFilename, AVIO_FLAG_WRITE) < 0) <br>        {<br>            rv = 1;<br>
        }<br>        else<br>        {<br>            /* Write the stream header, if any. */<br>            if (avformat_write_header(pOutputFormatCtx, NULL) < 0) <br>            {<br>                rv = 1;<br>            }<br>
        }<br>    }<br><br>    AVCodecContext *c = subtitle_st->codec;<br>    //--encoder--<br><br>    while( av_read_frame( pFormatCtx, &packet ) >= 0 )<br>    {<br>        if(packet.stream_index != subtitle_st->index)<br>
            continue;<br>        int gotSubtitle = 0;<br>        rv = avcodec_decode_subtitle2( pCodecCtxSubtitle, &subtitle, &gotSubtitle, &packet );<br>        uint64_t bufferSize = 1024 * 1024 ;<br>        uint8_t *buffer = new uint8_t[bufferSize];<br>
        memset(buffer, 0, bufferSize);<br>        if( rv >= 0 )<br>        {<br>            rv = avcodec_encode_subtitle( subtitle_st->codec, buffer, bufferSize, &subtitle );<br>            if ( rv >= 0 )<br>
            {<br>                AVPacket outPacket;<br>                av_init_packet(&outPacket);<br>                outPacket.data = buffer;<br>                outPacket.size = strlen((const char*)buffer);<br>                rv = av_interleaved_write_frame(pOutputFormatCtx, &outPacket);<br>
                av_free_packet(&outPacket);<br>            }<br>        }<br>        delete [] buffer;<br>    }<br><br>    if ( pCodecCtxSubtitle)        <br>    {<br>        avcodec_close(pCodecCtxSubtitle);<br>        pCodecCtxSubtitle= NULL;<br>
    }<br>    if ( pCodecSubtitle )            <br>    {<br>        av_free(pCodecSubtitle);<br>        pCodecSubtitle= NULL;<br>    }<br>    if ( pFormatCtx )<br>    {<br>        avformat_close_input(&pFormatCtx);<br>
        avformat_free_context(pFormatCtx);<br>        pFormatCtx = NULL;<br>    }<br>    avcodec_close(subtitle_st->codec);<br>    return rv;<br>}<br><br></div>Still, based on scenario posted with 1st email, it is not working. Hope to get some answers soon...<br>
<br>Thanks...<br><br></div></div>