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