I'm trying to do an all in-memory demux, mess around with data, then remux
of a TS stream. I'm finding that the output TS data has a PES frame for
every ADTS frame, which makes for some extra overhead. The ffmepg command
doesn't behave this way, so it seems like I must be missing an option or
something.
A simplified version of my code is attached. I've stripped the error
checking to make it super simple. I also changed the in-memory
reading/writing to just read/write from a file to make testing easier. I'm
building against the latest from git.
Is there an option to have the muxer handle bundling ADTS frames together
for me? Or do I need to do it myself before passing it
to av_interleaved_write_frame?
Also, is there anything that seems off with the way I'm using the
libavformat API? (aside form no error checking; that's intentional to make
the example code easier to read)
#include <stdlib.h>
#include <inttypes.h>
#include "libavutil/avutil.h"
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
static FILE *in_file = NULL;
static FILE *out_file = NULL;
static int read_cb(void *opaque, uint8_t *data, int size)
{
return fread(data, 1, size, in_file);
}
static int write_cb(void *opaque, uint8_t *data, int size)
{
return fwrite(data, 1, size, out_file);
}
int main(int argc, char *argv[])
{
int i;
AVFormatContext *ic = avformat_alloc_context();
AVFormatContext *oc;
int buf_size = 8192;
unsigned char *in_buf = (unsigned char *)av_malloc(buf_size);
unsigned char *out_buf = (unsigned char *)av_malloc(buf_size);
AVOutputFormat *fmt;
/*open input/output files*/
if (argc != 3)
{
fprintf(stderr, "Specify input and output files\n");
return 1;
}
in_file = fopen(argv[1], "rb");
out_file = fopen(argv[2], "wb");
if (!in_file || !out_file)
{
fprintf(stderr, "Unable to open specified file\n");
return 2;
}
avcodec_register_all();
av_register_all();
/*open input*/
ic->pb = avio_alloc_context(in_buf, buf_size, 0, NULL, read_cb,
NULL, NULL);
avformat_open_input(&ic, "dummy.ts", NULL, NULL);
avformat_find_stream_info(ic, NULL);
/*open output*/
fmt = av_guess_format("mpegts", NULL, NULL);
avformat_alloc_output_context2(&oc, fmt, NULL, NULL);
oc->pb = avio_alloc_context(out_buf, buf_size, 1, NULL, NULL,
write_cb, NULL);
/*copy stream info from input to output*/
for (i = 0; i < ic->nb_streams; i++)
{
AVStream *in_stream = ic->streams[i];
AVCodec *codec = avcodec_find_encoder(in_stream->codec->codec_id);
AVStream *out_stream = avformat_new_stream(oc, codec);
avcodec_parameters_from_context(out_stream->codecpar,
in_stream->codec);
/*copy common fields
Some of this may not be necessary anymore with codecpar, but
ffmpeg.c still uses it*/
out_stream->codec->codec_id = in_stream->codec->codec_id;
out_stream->codec->codec_type = in_stream->codec->codec_type;
out_stream->codec->bit_rate = in_stream->codec->bit_rate;
out_stream->codec->extradata = av_memdup(in_stream->codec->extradata,
in_stream->codec->extradata_size);
out_stream->codec->extradata_size = in_stream->codec->extradata_size;
out_stream->time_base.den = in_stream->time_base.den;
out_stream->time_base.num = in_stream->time_base.num;
/*copy audio and video specific fields*/
if (in_stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
out_stream->codec->width = in_stream->codec->width;
out_stream->codec->height = in_stream->codec->height;
out_stream->codec->pix_fmt = in_stream->codec->pix_fmt;
}
else
{
out_stream->codec->sample_fmt = in_stream->codec->sample_fmt;
out_stream->codec->sample_rate = in_stream->codec->sample_rate;
out_stream->codec->channels = in_stream->codec->channels;
}
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
/*start output*/
avformat_write_header(oc, NULL);
/*read frames from input and write them to output*/
while (1)
{
int ret;
AVPacket *pkt = (AVPacket *)av_malloc(sizeof(AVPacket));
av_init_packet(pkt);
/*read frame from input*/
ret = av_read_frame(ic, pkt);
if (ret)
{
av_free(pkt);
break;
}
/*write frame to output*/
av_interleaved_write_frame(oc, pkt);
/*cleanup*/
av_packet_unref(pkt);
av_free(pkt);
}
/*finish writing output*/
av_write_trailer(oc);
/*cleanup output*/
for (i = 0; i < oc->nb_streams; i++)
{
avcodec_close(oc->streams[i]->codec);
}
av_free(oc->pb->buffer);
av_freep(&oc->pb);
avformat_free_context(oc);
/*cleanup intput*/
for (i = 0; i < ic->nb_streams; i++)
{
avcodec_close(ic->streams[i]->codec);
}
av_free(ic->pb->buffer);
av_freep(&ic->pb);
avformat_close_input(&ic);
return 0;
}
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user