Skip to content

Instantly share code, notes, and snippets.

@brianmed
Created June 2, 2023 10:33
Show Gist options
  • Save brianmed/51ee69e570d62ab526de83989e3e343b to your computer and use it in GitHub Desktop.
Save brianmed/51ee69e570d62ab526de83989e3e343b to your computer and use it in GitHub Desktop.
Decode H264 Frame with FFmpeg
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
void my_log_callback(void *ptr, int level, const char *fmt, va_list vargs)
{
vprintf(fmt, vargs);
}
// LDFLAGS='-L/usr/local/Cellar/ffmpeg/6.0/lib -lavformat -lavcodec -lavutil -lswscale -lswresample' make joy
int main(void)
{
av_log_set_level(AV_LOG_VERBOSE);
av_log_set_callback(my_log_callback);
AVCodec *const codec = avcodec_find_decoder(AV_CODEC_ID_H264);
AVCodecContext* ctx = avcodec_alloc_context3(codec);
AVPacket pkt_bin;
AVPacket *thumbnail_packet = av_packet_alloc();
AVFrame *frame = av_frame_alloc();
struct stat st;
avcodec_open2(ctx, codec, NULL);
/// ffmpeg -ss 00:00:31 -i sintel.mp4 -f image2 -vframes 1 -vcodec copy -bsf h264_mp4toannexb frame.bin
stat("frame.bin", &st);
av_new_packet(&pkt_bin, st.st_size);
int bin_fh = open("frame.bin", O_RDONLY);
read(bin_fh, pkt_bin.data, st.st_size);
pkt_bin.size = st.st_size;
pkt_bin.pts = 1;
avcodec_send_packet(ctx, &pkt_bin);
avcodec_receive_frame(ctx, frame);
fprintf(stderr, "size: %dx%d\n", ctx->width, ctx->height);
//
AVCodec *thumbnail_codec = avcodec_find_encoder(AV_CODEC_ID_MJPEG);
AVCodecContext *thumbnail_encoder_codec_ctx = avcodec_alloc_context3(thumbnail_codec);
thumbnail_encoder_codec_ctx->width = ctx->width;
thumbnail_encoder_codec_ctx->height = ctx->height;
thumbnail_encoder_codec_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P;
thumbnail_encoder_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
thumbnail_encoder_codec_ctx->time_base = (AVRational){1, 30};
thumbnail_encoder_codec_ctx->framerate = (AVRational){30, 1};
avcodec_open2(thumbnail_encoder_codec_ctx, thumbnail_codec, NULL);
int error_code = avcodec_send_frame(thumbnail_encoder_codec_ctx, frame);
if (error_code >= 0)
{
error_code = avcodec_receive_packet(thumbnail_encoder_codec_ctx, thumbnail_packet);
FILE* out_JPEG = fopen("yay.jpeg", "wb");
fwrite(thumbnail_packet->data, thumbnail_packet->size, 1, out_JPEG);
fclose(out_JPEG);
}
fprintf(stderr, "error_code: %d\n", error_code);
av_frame_free(&frame);
av_packet_unref(&pkt_bin);
avcodec_free_context(&ctx);
avcodec_free_context(&thumbnail_encoder_codec_ctx);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment