[Libav-user] ASS subtitle header missing while encoding
Taha Ansari
mtaha.ansari at gmail.com
Mon Dec 9 10:55:14 CET 2013
Hi all!
I am writing a small test program that will convert .SRT subtitle file to
.ASS format.
original SRT file (subtitle.srt):
1
00:00:02,000 --> 00:00:06,000
Hello
2
00:00:15,000 --> 00:00:20,000
World
3
00:01:00,000 --> 00:01:10,000
!!Again!!
Demo code:
#include "stdafx.h"
//using namespace std;
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
//#include <DShow.h>
#include <conio.h>
#include <deque>
#include <queue>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavutil/dict.h"
#include "libavutil/error.h"
#include "libavutil/opt.h"
#include <libavutil/fifo.h>
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/time.h>
#include <libavformat/avio.h>
#include <libavutil/avstring.h>
#include <libavutil/mathematics.h>
#include "libavfilter/avfiltergraph.h"
#include "libavfilter/avcodec.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include <libswresample/swresample.h>
}
//++decoder++//
AVFormatContext *pFormatCtx = 0;
int subtitleIndex = -1;
AVPacket packet;
AVCodecContext *pCodecCtxSubtitle = 0;
AVCodec *pCodecSubtitle = 0;
AVSubtitle subtitle;
//--decoder--
//++encoder++
AVFormatContext *pOutputFormatCtx=0;
AVStream *subtitle_st=0;
AVOutputFormat *outputFmt=0;
AVCodec *subtitle_codec=0;
/* Add an output stream. */
AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
enum AVCodecID codec_id)
{
AVCodecContext *c;
AVStream *st;
/* find the encoder */
*codec = avcodec_find_encoder(codec_id);
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",
avcodec_get_name(codec_id));
exit(1);
}
st = avformat_new_stream(oc, *codec);
if (!st) {
fprintf(stderr, "Could not allocate stream\n");
exit(1);
}
st->id = oc->nb_streams-1;
c = st->codec;
avcodec_get_context_defaults3( c, *codec);
switch ((*codec)->type)
{
case AVMEDIA_TYPE_SUBTITLE:
break;
default:
break;
}
/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
return st;
}
void open_subtitle(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
int ret;
AVCodecContext *c = st->codec;
/* open the codec */
ret = avcodec_open2(c, codec, NULL);
if (ret < 0)
{
exit(1);
}
}
//--encoder--
int main (int argc, char **argv)
{
av_register_all();
avcodec_register_all();
avfilter_register_all();
char inputFilename[90]="subtitle.srt";
char outputFilename[90]="temp.ass";
int rv = 0;
// ++decoder++
int got_subtitle = 0;
pFormatCtx = avformat_alloc_context();
rv = avformat_open_input(&pFormatCtx, inputFilename, NULL, NULL);
for(int i=0; i < pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_SUBTITLE)
{
subtitleIndex = i;
}
}
if ( subtitleIndex >= 0 )
{
pCodecCtxSubtitle=pFormatCtx->streams[subtitleIndex]->codec;
pCodecSubtitle = avcodec_find_decoder(pCodecCtxSubtitle->codec_id);
if(pCodecSubtitle==NULL)
{
return -1; // Codec not found
}
// Open codec
AVDictionary *codecDictOptions = NULL;
if(avcodec_open2(pCodecCtxSubtitle, pCodecSubtitle,
&codecDictOptions) < 0 )//error
{
}
}
//--decoder--
//++encoder++
int ret;
avformat_alloc_output_context2(&pOutputFormatCtx, NULL, NULL,
outputFilename);
if (!pOutputFormatCtx)
{
rv = 1;
}
//outputFmt = pOutputFormatCtx->oformat;
outputFmt = av_guess_format( NULL, outputFilename, NULL );
if (outputFmt->subtitle_codec != AV_CODEC_ID_NONE)
{
subtitle_st = add_stream(pOutputFormatCtx, &subtitle_codec,
outputFmt->subtitle_codec);
}
if (subtitle_st)
open_subtitle(pOutputFormatCtx, subtitle_codec, subtitle_st);
av_dump_format(pOutputFormatCtx, 0, outputFilename, 1);
/* open the output file, if needed */
if (!(outputFmt->flags & AVFMT_NOFILE))
{
if (avio_open(&pOutputFormatCtx->pb, outputFilename,
AVIO_FLAG_WRITE) < 0)
{
rv = 1;
}
else
{
/* Write the stream header, if any. */
if (avformat_write_header(pOutputFormatCtx, NULL) < 0)
{
rv = 1;
}
}
}
AVCodecContext *c = subtitle_st->codec;
//--encoder--
while( av_read_frame( pFormatCtx, &packet ) >= 0 )
{
if(packet.stream_index != subtitle_st->index)
continue;
int gotSubtitle = 0;
rv = avcodec_decode_subtitle2( pCodecCtxSubtitle, &subtitle,
&gotSubtitle, &packet );
uint64_t bufferSize = 1024 * 1024 ;
uint8_t *buffer = new uint8_t[bufferSize];
memset(buffer, 0, bufferSize);
if( rv >= 0 )
{
rv = avcodec_encode_subtitle( subtitle_st->codec, buffer,
bufferSize, &subtitle );
if ( rv >= 0 )
{
AVPacket outPacket;
av_init_packet(&outPacket);
outPacket.data = buffer;
outPacket.size = strlen((const char*)buffer);
rv = av_interleaved_write_frame(pOutputFormatCtx,
&outPacket);
av_free_packet(&outPacket);
}
}
delete [] buffer;
}
if ( pCodecCtxSubtitle)
{
avcodec_close(pCodecCtxSubtitle);
pCodecCtxSubtitle= NULL;
}
if ( pCodecSubtitle )
{
av_free(pCodecSubtitle);
pCodecSubtitle= NULL;
}
if ( pFormatCtx )
{
avformat_close_input(&pFormatCtx);
avformat_free_context(pFormatCtx);
pFormatCtx = NULL;
}
avcodec_close(subtitle_st->codec);
return rv;
}
PTS values are not calculated still, it is work in progress; but the above
code gives me this output:
output temp.ass file:
Dialogue: 0,0:00:00.00,0:00:00.00,Default,Hello
Dialogue: 0,0:00:00.00,0:00:00.00,Default,World
Dialogue: 0,0:00:00.00,0:00:00.00,Default,!!Again!!
It is clearly missing all header information.
When i run ffmpeg command line to convert orignal SRT file using:
ffmpeg -i subtitle.srt temp.ass
I get:
[Script Info]
ScriptType: v4.00+
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour,
OutlineColour, BackColour, Bold, Italic, Underline, BorderStyle, Outline,
Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding
Style: Default,Arial,16,&Hffffff,&Hffffff,&H0,&H0,0,0,0,1,1,0,2,10,10,10,0,0
[Events]
Format: Layer, Start, End, Style, Text
Dialogue: 0,0:00:02.00,0:00:06.00,Default,Hello
Dialogue: 0,0:00:15.00,0:00:20.00,Default,World
Dialogue: 0,0:01:00.00,0:01:10.00,Default,!!Again!!
so my question is, even though I am calling avformat_write_header()
function, why isn't this header information being written through my code?
Thanks in advance...
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20131209/9ff6ae03/attachment.html>
More information about the Libav-user
mailing list