Hello..

I'm working on a small project to clip portions mpeg transport streams and save 
them to a new file. These may be with or without audio. For the most part 
things are working great (libavformat has be a great help). However, I run into 
problem once I start using content which have b-frames present (i and p 
frame-only content work as expected). In the b-frame case, the generated 
transport streams play back choppy (on multiple players). I've examined the 
content of the new streams and it looks like the PTS information is getting 
jumbled in the generated file.. I have not been changing any of the PTS 
information in my code. 

I've sifted through the docs/headers, FAQ and google in general but haven't 
really found anything about this. Are mpeg b-frames not supported or am I 
missing something..

I've attached a simple example that I wrote which simply copies one stream to 
another. If you run this with a source MPEG-2 transport stream which has 
b-frames present you can see exactly what I described above. I can also supply 
a source file if it's needed...

Just looking for some suggestions or insight from folks with a bit more 
experience developing with libavformat.

Thanks,

-Smitty


//
// Compile:
//      g++ -g -I/usr/local/include copy-ts.cpp -L/usr/local/lib -lavformat 
-lbz2 -lm -o copy-ts
//
// Usage: copy-ts <src_file.ts> <dest_file.ts>
//
#include <stdio.h>
#include <assert.h>
#include <string.h>

extern "C" 
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}

void dump_packet(const AVPacket *packet, const char *tag)
{
    printf("Packet (%s)\n", tag);
    printf("  stream:    %d\n",    packet->stream_index);
    printf("  keyframe:  %d\n",    (packet->flags & PKT_FLAG_KEY));
    printf("  pts:       %lld\n",  packet->pts);
    printf("  dts:       %lld\n",  packet->dts);
    printf("  size:      %d\n",    packet->size);
    printf("  duration:  %d\n",    packet->duration);
    printf("  flags:     %d\n",    packet->flags);
    printf("  data:      0x%x\n",  packet->data);
}

int main(int argc, char *argv[]) 
{
    assert(argc >= 3);
    
    const char *inFile  = argv[1];
    const char *outFile = argv[2];
    
    // Registration
    av_register_all();
    
    // Open source
    AVFormatContext *inContext;
    int status = av_open_input_file(&inContext, inFile, NULL, 0, NULL);
    assert(status >= 0);
    
    av_find_stream_info(inContext);
    assert(status >= 0);
   
     // Create a new output context
    AVFormatContext *outContext = av_alloc_format_context();
    
    // Specify the destination file
    strncpy(outContext->filename, inFile, 1024);
    
    // Determine the output format
    outContext->oformat = guess_stream_format(NULL, outFile, NULL);
    assert(outContext->oformat != NULL);
    
    // Open destination
    status = url_fopen(&outContext->pb, outFile, URL_WRONLY);
    assert(status >= 0);

    // Setup
    av_set_parameters(outContext, NULL);
    for(int i=0; i < inContext->nb_streams; i++) 
    {
        // Create new stream
        AVStream *inStream  = inContext->streams[i];
        AVStream *outStream = av_new_stream(outContext, i);
        assert(outStream != NULL);
        
        // Use identical stream information
        outStream->pts.num       = inStream->pts.num;
        outStream->pts.den       = inStream->pts.den;
        outStream->time_base.num = inStream->time_base.num;
        outStream->time_base.den = inStream->time_base.den;
        outStream->codec         = inStream->codec;
    }
    
    // Header
    status = av_write_header(outContext);
    assert(status == 0);
    
    // Init packet
    AVPacket packet;
    av_init_packet(&packet);

    // Read/Write packets
    bool done = false;
    do
    {
        status = av_read_frame(inContext, &packet);
        if(status >= 0)
        {
            //dump_packet(&packet, "read");
            status = av_write_frame(outContext, &packet);
            assert(status >= 0);
        
            av_free_packet(&packet);
        }
        else 
            done = true;
    }
    while(!done);
    
    // Trailer
    status = av_write_trailer(outContext);
    assert(status == 0);
            
    // Close files
    av_close_input_file(inContext);
    url_fclose(outContext->pb);
}

_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to