smallpond

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/smallpond
Log | Files | Refs | README | LICENSE

commit 870db5d80c0ad8f0bfb281de0c4272802f884b6d
parent a465a319e38f7c2638e68f76d9a1c1fbbbaabe1b
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Thu, 27 Oct 2022 21:11:20 -0500

use matroska

Diffstat:
MMakefile | 2+-
Mmain.c | 67++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,5 +1,5 @@ smallpond: main.c - gcc -o smallpond main.c $(shell pkg-config --cflags --libs lua) $(shell pkg-config --cflags --libs freetype2) $(shell pkg-config --cflags --libs cairo) $(shell pkg-config --cflags --libs libavcodec) $(shell pkg-config --cflags --libs libavutil) + gcc -o smallpond main.c $(shell pkg-config --cflags --libs lua) $(shell pkg-config --cflags --libs freetype2) $(shell pkg-config --cflags --libs cairo) $(shell pkg-config --cflags --libs libavcodec) $(shell pkg-config --cflags --libs libavutil) $(shell pkg-config --cflags --libs libavformat) clean: diff --git a/main.c b/main.c @@ -10,6 +10,7 @@ #include <cairo.h> #include <libavcodec/avcodec.h> +#include <libavformat/avformat.h> #include <libavutil/frame.h> #include <lua.h> @@ -110,7 +111,7 @@ create_surface(lua_State *L) } int -putframe(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) +putframe(AVFormatContext *fctx, const AVStream *st, AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt) { int ret; @@ -129,11 +130,20 @@ putframe(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) exit(1); } - fwrite(pkt->data, 1, pkt->size, out); + av_packet_rescale_ts(pkt, ctx->time_base, st->time_base); + pkt->stream_index = st->index; + + ret = av_interleaved_write_frame(fctx, pkt); + if (ret < 0) { + fprintf(stderr, "failed to write video frame\n"); + exit(1); + } av_packet_unref(pkt); } } +#define FILENAME "out.mkv" + int main(int argc, char *argv[]) { @@ -172,12 +182,6 @@ main(int argc, char *argv[]) return 1; } - FILE *output = fopen("out.h264", "wb"); - if (!output) { - fprintf(stderr, "couldn't open output\n"); - return 1; - } - AVPacket *pkt = av_packet_alloc(); if (!pkt) { fprintf(stderr, "couldn't allocate packet!\n"); @@ -190,19 +194,40 @@ main(int argc, char *argv[]) return 1; } + const AVOutputFormat *fmt = av_guess_format(NULL, FILENAME, NULL); + if (!fmt) { + fprintf(stderr, "unknown output format\n"); + return 1; + } + + AVFormatContext *fc = avformat_alloc_context(); + if (!fc) { + fprintf(stderr, "couldn't allocate AVFormatContext\n"); + return 1; + } + + fc->oformat = fmt; + const AVCodec *codec = avcodec_find_encoder_by_name("libx264rgb"); if (!codec) { fprintf(stderr, "couldn't find h264 codec!\n"); return 1; } + AVStream *stream = avformat_new_stream(fc, NULL); + stream->id = fc->nb_streams-1; + AVCodecContext *c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "couldn't alloc AVCodec context!\n"); return 1; } + if (fc->oformat->flags & AVFMT_GLOBALHEADER) + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + // suggested bitrates: https://www.videoproc.com/media-converter/bitrate-setting-for-h264.htm + c->codec_id = codec->id; c->bit_rate = 2500*1000; c->width = 854; c->height = 480; @@ -214,6 +239,7 @@ main(int argc, char *argv[]) c->gop_size = 30*3; AVDictionary *opts = NULL; + stream->time_base = c->time_base; frame->format = c->pix_fmt; frame->width = c->width; frame->height = c->height; @@ -243,6 +269,23 @@ main(int argc, char *argv[]) return 1; } + if (!(fmt->flags & AVFMT_NOFILE)) { + if (avio_open(&fc->pb, FILENAME, AVIO_FLAG_WRITE) < 0) { + fprintf(stderr, "failed to open output file\n"); + } + } + + if (avcodec_parameters_from_context(stream->codecpar, c) < 0) { + fprintf(stderr, "failed to copy stream parameters\n"); + return 1; + } + + int ret; + if ((ret = avformat_write_header(fc, NULL)) < 0) { + fprintf(stderr, "failed to write header: %s\n", av_err2str(ret)); + return 1; + } + bool done = false; double time = 0; double framecount = 0; @@ -280,18 +323,20 @@ main(int argc, char *argv[]) fflush(stdout); frame->pts = framecount; - putframe(c, frame, pkt, output); + putframe(fc, stream, c, frame, pkt); time += 0.00390625; framecount += 1; } - putframe(c, NULL, pkt, output); - fclose(output); + av_write_trailer(fc); avcodec_free_context(&c); av_frame_free(&frame); av_packet_free(&pkt); + avio_closep(&fc->pb); + avformat_free_context(fc); + cairo_destroy(cr); cairo_surface_destroy(surface); lua_close(L);