55 lines
2.4 KiB
C
55 lines
2.4 KiB
C
// Generate a deterministic 1440p H.264 clip without any display/capture dependency.
|
|
// Link against the isolated FFmpeg libavcodec/libavutil built for the terminal.
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <libavcodec/avcodec.h>
|
|
#include <libavutil/opt.h>
|
|
|
|
static int write_packets(AVCodecContext *encoder, AVPacket *packet, FILE *output) {
|
|
int result;
|
|
while ((result = avcodec_receive_packet(encoder, packet)) == 0) {
|
|
if (fwrite(packet->data, 1, packet->size, output) != (size_t)packet->size) return -1;
|
|
av_packet_unref(packet);
|
|
}
|
|
return result == AVERROR(EAGAIN) || result == AVERROR_EOF ? 0 : result;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
if (argc != 2) return 2;
|
|
const AVCodec *codec = avcodec_find_encoder_by_name("libx264");
|
|
AVCodecContext *encoder = avcodec_alloc_context3(codec);
|
|
AVFrame *frame = av_frame_alloc();
|
|
AVPacket *packet = av_packet_alloc();
|
|
FILE *output = fopen(argv[1], "wb");
|
|
if (!codec || !encoder || !frame || !packet || !output) return 1;
|
|
encoder->width = frame->width = 2560;
|
|
encoder->height = frame->height = 1440;
|
|
encoder->pix_fmt = frame->format = AV_PIX_FMT_YUV420P;
|
|
encoder->time_base = (AVRational){1, 30};
|
|
encoder->framerate = (AVRational){30, 1};
|
|
encoder->max_b_frames = 0;
|
|
encoder->thread_count = 2;
|
|
av_opt_set(encoder->priv_data, "preset", "ultrafast", 0);
|
|
av_opt_set(encoder->priv_data, "tune", "zerolatency", 0);
|
|
if (avcodec_open2(encoder, codec, NULL) < 0 || av_frame_get_buffer(frame, 32) < 0) return 1;
|
|
for (int i = 0; i < 60; i++) {
|
|
if (av_frame_make_writable(frame) < 0) return 1;
|
|
for (int y = 0; y < frame->height; y++) {
|
|
memset(frame->data[0] + y * frame->linesize[0], 32 + (y + i * 4) % 190, frame->width);
|
|
}
|
|
for (int plane = 1; plane < 3; plane++) {
|
|
for (int y = 0; y < frame->height / 2; y++) {
|
|
memset(frame->data[plane] + y * frame->linesize[plane], 128, frame->width / 2);
|
|
}
|
|
}
|
|
frame->pts = i;
|
|
if (avcodec_send_frame(encoder, frame) < 0 || write_packets(encoder, packet, output) < 0) return 1;
|
|
}
|
|
if (avcodec_send_frame(encoder, NULL) < 0 || write_packets(encoder, packet, output) < 0) return 1;
|
|
if (fclose(output) != 0) return 1;
|
|
av_packet_free(&packet);
|
|
av_frame_free(&frame);
|
|
avcodec_free_context(&encoder);
|
|
return 0;
|
|
}
|