Skip to content

Instantly share code, notes, and snippets.

@aconz2
Created April 13, 2020 18:55
Show Gist options
  • Save aconz2/7f21af747c593498c8a40131fac3cba5 to your computer and use it in GitHub Desktop.
Save aconz2/7f21af747c593498c8a40131fac3cba5 to your computer and use it in GitHub Desktop.
Example using lib{avformat,codec} to demux and decode frames of a container file
// clang -g -O2 -I/usr/include/ffmpeg -lavformat -lavutil -lavcodec avformat_example.c -o avformat_example
#include <assert.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/file.h>
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: <input_file>\n");
return 1;
}
AVFormatContext *fmt_ctx = NULL;
AVCodec *codec = NULL;
char *input_filename = argv[1];
int ret = 0;
ret = avformat_open_input(&fmt_ctx, input_filename, NULL, NULL); assert(ret == 0);
ret = avformat_find_stream_info(fmt_ctx, NULL); assert(ret == 0);
av_dump_format(fmt_ctx, 0, input_filename, 0);
int videostream = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &codec, 0); assert(videostream >= 0);
assert(codec); // codec gets filled in for us
printf("Video stream is stream %d\n", videostream);
printf("Codec is %s -- %s\n", codec->name, codec->long_name);
AVCodecContext *dec_ctx = avcodec_alloc_context3(codec); assert(dec_ctx);
ret = avcodec_parameters_to_context(dec_ctx, fmt_ctx->streams[videostream]->codecpar); assert(ret == 0);
ret = avcodec_open2(dec_ctx, codec, NULL); assert(ret == 0);
AVPacket *pkt = av_packet_alloc(); assert(pkt);
AVFrame *frame = av_frame_alloc(); assert(frame);
struct timespec tw1, tw2;
clock_gettime(CLOCK_MONOTONIC, &tw1);
size_t frames = 0;
for(;;) {
ret = av_read_frame(fmt_ctx, pkt);
if (ret < 0) break; // TODO flush the decoder
if (pkt->stream_index == videostream) {
/* printf("Got packet idx=%d pts=%ld size=%d data=%llx bufsize=%d\n", pkt->stream_index, pkt->pts, pkt->size, (unsigned long long)pkt->data, pkt->buf->size); */
ret = avcodec_send_packet(dec_ctx, pkt); assert(ret == 0);
/* printf("%d %d %d %d\n", ret, AVERROR(EAGAIN), AVERROR(EINVAL), AVERROR(ENOMEM)); */
do {
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret < 0) break;
frames += 1;
/* printf("frame number %d\n", dec_ctx->frame_number); */
} while (ret >= 0);
} else {
}
}
clock_gettime(CLOCK_MONOTONIC, &tw2);
double elapsed = (1000.0*tw2.tv_sec + 1e-6*tw2.tv_nsec - (1000.0*tw1.tv_sec + 1e-6*tw1.tv_nsec)) / 1000;
printf("Decoded %ld frames in %.2f seconds : %.2f fps\n", frames, elapsed, (double)frames / elapsed);
av_frame_free(&frame);
avcodec_free_context(&dec_ctx);
av_packet_unref(pkt);
avformat_close_input(&fmt_ctx);
avcodec_close(dec_ctx);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment