Reputation: 11
I can't seem to get anything useful out of the AVPacket.data I'm writing. It's not generating valid video files and they're incredibly small. 4Mb converts to ~300Kb. They're not playing and VLC reports their formats as "undf" (missing headers?). I'm stuck and need some help moving on.
Here's the decode-encode snippet:
// initialize the output context
ctx_out = avformat_alloc_context();
// guess container format
ctx_out->oformat = av_guess_format(NULL, out_file_name, NULL);
snprintf(ctx_out->filename, sizeof(ctx_out->filename), "%s", out_file_name);
// .. stripped: creates video stream, encoder and its codec
if ((res = avio_open2(&ctx_out->pb, out_file_name, AVIO_FLAG_WRITE, NULL, NULL)) != 0) {
callback_with_error(options, "Failed to open output file for writing (%s)", res);
return;
}
if ((res = avformat_write_header(ctx_out, NULL)) != 0) {
callback_with_error(options, "Failed to write output format header (%s)", res);
return;
}
av_init_packet(&packet);
while (av_read_frame(ctx_format, &packet) >= 0) {
frame_finished = 0;
total_size += packet.size;
if (packet.stream_index == video_stream) {
len = avcodec_decode_video2(decoder_video, frame, &frame_finished, &packet);
if (len < 0) {
callback_with_error(options, "Frame #%d video decoding error (%d)", current_frame, len);
return;
}
if (frame_finished) {
len = avcodec_encode_video2(encoder_video, &packet, frame, &frame_finished);
if (len < 0) {
continue; // dropped?
}
if (frame_finished) {
if ((res = av_interleaved_write_frame(ctx_out, &packet)) != 0) {
callback_with_error(options, "Output write error (%d).", res);
return;
}
}
}
if (frame_finished) {
current_frame++;
}
} else if (packet.stream_index == audio_stream) {
// audio
}
}
av_free_packet(&packet);
av_write_trailer(ctx_out);
for(i = 0; i < ctx_out->nb_streams; i++) {
av_freep(&ctx_out->streams[i]->codec);
av_freep(&ctx_out->streams[i]);
}
if (!(ctx_out->oformat->flags & AVFMT_NOFILE)) {
avio_close(ctx_out->pb);
}
av_free(ctx_out);
I'm hoping there's someone on SO with a bit of knowledge about how LibAV works. I've looked at the examples and read various "articles" about how to use it. So, yeah, I'm stuck for now.
Thanks.
Upvotes: 1
Views: 536
Reputation:
What you're currently doing here is writing the raw content of each video packet to the output file without any sort of container or framing. While this will sort of work for a few special formats (such as MPEG1 video and MP3 audio streams), it does not work in general -- you will need to open up an AVFormatContext
(using avformat_write_header
), write each packet to the stream using av_interleaved_write_frame
(or av_write_frame
if your stream is already properly interleaved), then tie up all the loose ends using av_write_trailer
.
Upvotes: 1