Skip to content

Instantly share code, notes, and snippets.

@J0sueTM
Created October 24, 2023 11:39
Show Gist options
  • Save J0sueTM/78308eefaa130153e4a513767a0b9dcc to your computer and use it in GitHub Desktop.
Save J0sueTM/78308eefaa130153e4a513767a0b9dcc to your computer and use it in GitHub Desktop.
ffmpeg encode video
#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libavutil/error.h>
static void print_ret_error(int ret) {
char buf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, buf, sizeof(buf));
printf("%s\n", buf);
}
static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *packet, FILE *output) {
int ret = avcodec_send_frame(ctx, frame);
if (ret < 0) {
printf("failed to send frame %ld to encoder\n", frame->pts);
print_ret_error(ret);
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_packet(ctx, packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
return;
} else if (ret < 0) {
printf("failed to encode frame %ld\n", frame->pts);
print_ret_error(ret);
exit(1);
}
printf("writing packet %ld (size=%5d)\n", packet->pts, packet->size);
fwrite(packet->data, 1, packet->size, output);
av_packet_unref(packet);
}
}
int main(int _argc, char **_argv) {
if (_argc <= 2) {
printf("usage: %s <codec name> <output file>\n", _argv[0]);
return 0;
}
const char *codec_name = _argv[1];
const char *filename = _argv[2];
const AVCodec *codec = avcodec_find_encoder_by_name(codec_name);
if (!codec) {
printf("failed to find encoder codec\n");
return 1;
}
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
printf("failed to alloc codec context\n");
return 1;
}
codec_ctx->bit_rate = 400000;
codec_ctx->width = 352;
codec_ctx->height = 288;
codec_ctx->time_base = (AVRational){1, 25};
codec_ctx->framerate = (AVRational){25, 1};
codec_ctx->gop_size = 10;
codec_ctx->max_b_frames = 1;
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
if (codec->id == AV_CODEC_ID_H264) {
av_opt_set(codec_ctx->priv_data, "preset", "slow", 0);
}
int ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {
printf("failed to open codec\n");
return 1;
}
FILE *output = fopen(filename, "wb");
if (!output) {
printf("failed to open output file\n");
return 1;
}
AVFrame *frame = av_frame_alloc();
AVPacket *packet = av_packet_alloc();
if (!packet || !frame) {
printf("failed to alloc packet or frame\n");
return 1;
}
frame->format = codec_ctx->pix_fmt;
frame->width = codec_ctx->width;
frame->height = codec_ctx->height;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {
printf("failed to allocate video frame data\n");
}
for (int i = 0; i < (10 * 25); ++i) {
ret = av_frame_make_writable(frame);
if (ret < 0) {
printf("failed to make frame writable\n");
return 1;
}
// luma (Y)
for (int y = 0; y < codec_ctx->height; ++y) {
for (int x = 0; x < codec_ctx->width; ++x) {
frame->data[0][y * frame->linesize[0] + x] = x + y + i * 4;
}
}
for (int y = 0; y < codec_ctx->height * 0.5f; ++y) {
for (int x = 0; x < codec_ctx->width * 0.5f; ++x) {
// chroma blue (U)
frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 5;
// chroma red (V)
frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 2;
}
}
frame->pts = i;
encode(codec_ctx, frame, packet, output);
}
encode(codec_ctx, NULL, packet, output);
fclose(output);
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
av_packet_free(&packet);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment