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

Reply via email to