From e7fae576784151f49a8462930b38fbdedb2ddbe9 Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 14 Jan 2024 17:51:26 +0100 Subject: [PATCH] Add video-player -h, -w, and -z options to select the window size. Restore extradata codec support that was previously removed when libavcodec was updated and no replacement was known yet. This makes many codecs start working again. Convert video-player to C while here and remove dispd support. --- ports/video-player/video-player.patch | 234 +++++++++++++------------- ports/video-player/video-player.port | 1 + 2 files changed, 122 insertions(+), 113 deletions(-) diff --git a/ports/video-player/video-player.patch b/ports/video-player/video-player.patch index daf58eb6..c2537834 100644 --- a/ports/video-player/video-player.patch +++ b/ports/video-player/video-player.patch @@ -1,7 +1,7 @@ diff -Paur --no-dereference -- video-player.upstream/Makefile video-player/Makefile --- video-player.upstream/Makefile +++ video-player/Makefile -@@ -0,0 +1,36 @@ +@@ -0,0 +1,29 @@ +include ../../../build-aux/compiler.mak +include ../../../build-aux/version.mak +include ../../../build-aux/dirs.mak @@ -9,28 +9,21 @@ diff -Paur --no-dereference -- video-player.upstream/Makefile video-player/Makef +PKG_CONFIG?=pkg-config + +OPTLEVEL?=-g -O2 -+CXXFLAGS?=$(OPTLEVEL) ++CFLAGS?=$(OPTLEVEL) + +CPPFLAGS:=$(CPPFLAGS) -+CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti ++CFLAGS:=$(CFLAGS) -Wall -Wextra + +BINARY:=video-player +LIBS!=$(PKG_CONFIG) --libs libavcodec libavformat libswscale -+ -+DISPLAY:=$(shell $(LD) -ldisplay -o /dev/null 2>/dev/null && echo 1) -+ifeq ($(DISPLAY),1) +LIBS:=$(LIBS) -ldisplay -+CPPFLAGS:=$(CPPFLAGS) -DDISPLAY -+else -+LIBS:=$(LIBS) -ldispd -+endif + +all: $(BINARY) + +.PHONY: all install clean + -+%: %.cpp -+ $(CXX) -std=gnu++11 $(CXXFLAGS) $(CPPFLAGS) $< -o $@ $(LIBS) ++%: %.c ++ $(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $< -o $@ $(LIBS) + +install: all + mkdir -p $(DESTDIR)$(BINDIR) @@ -38,16 +31,32 @@ diff -Paur --no-dereference -- video-player.upstream/Makefile video-player/Makef + +clean: + rm -f $(BINARY) -diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-player/video-player.cpp ---- video-player.upstream/video-player.cpp -+++ video-player/video-player.cpp -@@ -0,0 +1,302 @@ -+#define __STDC_CONSTANT_MACROS -+#define __STDC_LIMIT_MACROS +diff -Paur --no-dereference -- video-player.upstream/video-player.c video-player/video-player.c +--- video-player.upstream/video-player.c ++++ video-player/video-player.c +@@ -0,0 +1,317 @@ ++/* ++ * Copyright (c) 2016, 2021, 2022, 2024 Jonas 'Sortie' Termansen. ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ * video-player.c ++ * Play videos. ++ */ + +#include ++#include +#include -+#include +#include +#include +#include @@ -55,110 +64,111 @@ diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-play +#include +#include + -+#ifdef DISPLAY +#include -+#else -+#include -+#endif + -+extern "C" { +#include +#include +#include -+} // extern "C" + -+uint32_t WINDOW_ID = 0; -+uint32_t WINDOW_WIDTH = 0; -+uint32_t WINDOW_HEIGHT = 0; ++static uint32_t WINDOW_ID = 0; ++static uint32_t WINDOW_WIDTH = 0; ++static uint32_t WINDOW_HEIGHT = 0; + -+bool need_show = true; -+bool need_exit = false; ++static int force_width = 0; ++static int force_height = 0; ++static int zoom = 100; + -+uint32_t* framebuffer = NULL; -+size_t framebuffer_size = 0; ++static bool need_show = true; ++static bool need_exit = false; + -+void on_disconnect(void*) ++static uint32_t* framebuffer = NULL; ++static size_t framebuffer_size = 0; ++ ++static void on_disconnect(void* ctx) +{ + need_exit = true; +} + -+void on_quit(void*, uint32_t window_id) ++static void on_quit(void* ctx, uint32_t window_id) +{ + if ( window_id != WINDOW_ID ) + return; + need_exit = true; +} + -+void on_resize(void*, uint32_t window_id, uint32_t width, uint32_t height) ++static void on_resize(void* ctx, uint32_t window_id, uint32_t width, ++ uint32_t height) +{ + if ( window_id != WINDOW_ID ) + return; + WINDOW_WIDTH = width; + WINDOW_HEIGHT = height; ++ force_width = width; ++ force_height = height; ++ zoom = 100; +} + -+void on_keyboard(void*, uint32_t window_id, uint32_t) ++static void on_keyboard(void* ctx, uint32_t window_id, uint32_t codepoint) +{ + if ( window_id != WINDOW_ID ) + return; +} + -+#ifdef DISPLAY -+static void DisplayVideoFrame(AVFrame* frame, struct display_connection* connection) -+#else -+static void DisplayVideoFrame(AVFrame* frame, struct dispd_window* window) -+#endif ++static void display_video_frame(AVFrame* frame, ++ struct display_connection* connection) +{ -+#ifdef DISPLAY ++ if ( need_show ) ++ { ++ WINDOW_WIDTH = ++ force_width ? force_width : (frame->width * zoom) / 100; ++ WINDOW_HEIGHT = ++ force_height ? force_height : (frame->height * zoom) / 100; ++ display_resize_window(connection, WINDOW_ID, WINDOW_WIDTH, ++ WINDOW_HEIGHT); ++ } ++ ++ if ( !WINDOW_WIDTH || !WINDOW_HEIGHT ) ++ return; ++ + size_t framebuffer_needed = sizeof(uint32_t) * WINDOW_WIDTH * WINDOW_HEIGHT; + if ( framebuffer_size != framebuffer_needed ) + { -+ framebuffer = (uint32_t*) realloc(framebuffer, framebuffer_size = framebuffer_needed); ++ framebuffer = ++ (uint32_t*) realloc(framebuffer, ++ framebuffer_size = framebuffer_needed); + memset(framebuffer, 255, framebuffer_needed); + } + uint32_t width = WINDOW_WIDTH; + uint32_t height = WINDOW_HEIGHT; -+#else -+ struct dispd_framebuffer* window_fb = dispd_begin_render(window); -+ uint32_t width = dispd_get_framebuffer_width(window_fb); -+ uint32_t height = dispd_get_framebuffer_height(window_fb); -+ uint32_t* framebuffer = (uint32_t*) dispd_get_framebuffer_data(window_fb); -+#endif + -+ SwsContext* sws_ctx = sws_getContext(frame->width, frame->height, -+ (AVPixelFormat) frame->format, width, -+ height, AV_PIX_FMT_RGB32, SWS_BILINEAR, -+ NULL, NULL, NULL); ++ struct SwsContext* sws_ctx = ++ sws_getContext(frame->width, frame->height, ++ (enum AVPixelFormat) frame->format, width, height, ++ AV_PIX_FMT_RGB32, SWS_BILINEAR, NULL, NULL, NULL); + assert(sws_ctx); + + uint8_t* data_arr[1] = { (uint8_t*) framebuffer }; + int stride_arr[1] = { (int) (sizeof(framebuffer[0]) * width) }; -+ sws_scale(sws_ctx, frame->data, frame->linesize, 0, frame->height, data_arr, -+ stride_arr); ++ ++ sws_scale(sws_ctx, (const uint8_t * const*) frame->data, frame->linesize, 0, ++ frame->height, data_arr, stride_arr); + + sws_freeContext(sws_ctx); + -+#ifdef DISPLAY -+ display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, framebuffer); ++ display_render_window(connection, WINDOW_ID, 0, 0, WINDOW_WIDTH, ++ WINDOW_HEIGHT, framebuffer); + -+ struct display_event_handlers handlers; -+ memset(&handlers, 0, sizeof(handlers)); -+ handlers.disconnect_handler = on_disconnect; -+ handlers.quit_handler = on_quit; -+ handlers.resize_handler = on_resize; -+ handlers.keyboard_handler = on_keyboard; -+ while ( display_poll_event(connection, &handlers) == 0 ); -+#else -+ dispd_finish_render(window_fb); -+#endif ++ if ( need_show ) ++ { ++ display_show_window(connection, WINDOW_ID); ++ need_show = false; ++ } +} + -+#ifdef DISPLAY -+bool PlayVideo(const char* path, struct display_connection* connection) -+#else -+bool PlayVideo(const char* path, struct dispd_window* connection) -+#endif ++bool play_video(const char* path, struct display_connection* connection) +{ ++ need_show = true; ++ + bool ret = false; + int av_error; + AVFormatContext* format_ctx = NULL; @@ -176,13 +186,13 @@ diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-play + + if ( (av_error = avformat_open_input(&format_ctx, path, NULL, NULL)) < 0 ) + { -+ error(0, 0, "%s: cannot open: %i\n", path, av_error); ++ warnx("%s: cannot open: %i\n", path, av_error); + goto cleanup_done; + } + + if ( (av_error = avformat_find_stream_info(format_ctx, NULL)) < 0 ) + { -+ error(0, 0, "%s: avformat_find_stream_info: %i\n", path, av_error); ++ warnx("%s: avformat_find_stream_info: %i\n", path, av_error); + goto cleanup_input; + } + @@ -198,23 +208,28 @@ diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-play + + if ( !video_stream ) + { -+ error(0, 0, "%s: no video stream found\n", path); ++ warnx("%s: no video stream found\n", path); + goto cleanup_input; + } + -+ if ( video_codec && !(video_codec_ctx = avcodec_alloc_context3(video_codec))) ++ if ( video_codec && ++ !(video_codec_ctx = avcodec_alloc_context3(video_codec))) + goto cleanup_input; -+ if ( audio_codec && !(audio_codec_ctx = avcodec_alloc_context3(audio_codec))) ++ if ( audio_codec && ++ !(audio_codec_ctx = avcodec_alloc_context3(audio_codec))) + goto cleanup_video_codec_ctx; + -+ + if ( video_codec_ctx ) + { ++ video_codec_ctx->extradata = video_stream->codecpar->extradata; ++ video_codec_ctx->extradata_size = video_stream->codecpar->extradata_size; + if ( (av_error = avcodec_open2(video_codec_ctx, NULL, NULL)) < 0 ) + goto cleanup_audio_codec_ctx; + } + if ( audio_codec_ctx ) + { ++ audio_codec_ctx->extradata = audio_stream->codecpar->extradata; ++ audio_codec_ctx->extradata_size = audio_stream->codecpar->extradata_size; + if ( (av_error = avcodec_open2(audio_codec_ctx, NULL, NULL)) < 0 ) + goto cleanup_audio_codec_ctx; + } @@ -247,12 +262,21 @@ diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-play + clock_gettime(CLOCK_MONOTONIC, &now); + } + -+ DisplayVideoFrame(video_frame, connection); ++ display_video_frame(video_frame, connection); + + uintmax_t usecs = video_codec_ctx->ticks_per_frame * 1000000 * + video_codec_ctx->time_base.num / + video_codec_ctx->time_base.den; -+ next_frame_at = timespec_add(next_frame_at, timespec_make(0, usecs * 1000)); ++ next_frame_at = ++ timespec_add(next_frame_at, timespec_make(0, usecs * 1000)); ++ ++ struct display_event_handlers handlers; ++ memset(&handlers, 0, sizeof(handlers)); ++ handlers.disconnect_handler = on_disconnect; ++ handlers.quit_handler = on_quit; ++ handlers.resize_handler = on_resize; ++ handlers.keyboard_handler = on_keyboard; ++ while ( display_poll_event(connection, &handlers) == 0 ); + } + if ( av_error != AVERROR(EAGAIN) && av_error != AVERROR_EOF ) + goto break_decode_loop; @@ -280,12 +304,14 @@ diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-play +cleanup_audio_codec_ctx: + if ( audio_codec_ctx ) + { ++ audio_codec_ctx->extradata = NULL; + avcodec_close(audio_codec_ctx); + av_free(audio_codec_ctx); + } +cleanup_video_codec_ctx: + if ( video_codec_ctx ) + { ++ video_codec_ctx->extradata = NULL; + avcodec_close(video_codec_ctx); + av_free(video_codec_ctx); + } @@ -297,50 +323,32 @@ diff -Paur --no-dereference -- video-player.upstream/video-player.cpp video-play + +int main(int argc, char* argv[]) +{ -+#ifdef DISPLAY ++ int opt; ++ while ( (opt = getopt(argc, argv, "h:w:z:")) != -1 ) ++ { ++ switch ( opt ) ++ { ++ case 'h': force_height = atoi(optarg); break; ++ case 'w': force_width = atoi(optarg); break; ++ case 'z': zoom = atoi(optarg); break; ++ default: return 1; ++ } ++ } ++ + struct display_connection* connection = display_connect_default(); + if ( !connection ) -+ error(1, errno, "Could not connect to display server"); -+#else -+ if ( !isatty(0) ) -+ error(1, errno, "standard input"); -+ if ( !dispd_initialize(&argc, &argv) ) -+ error(1, 0, "couldn't initialize dispd library"); -+ struct dispd_session* session = dispd_attach_default_session(); -+ if ( !session ) -+ error(1, 0, "couldn't attach to dispd default session"); -+ if ( !dispd_session_setup_game_rgba(session) ) -+ error(1, 0, "couldn't setup dispd rgba session"); -+ struct dispd_window* window = dispd_create_window_game_rgba(session); -+ if ( !window ) -+ error(1, 0, "couldn't create dispd rgba window"); -+ struct dispd_window* connection = window; -+#endif -+ -+#ifdef DISPLAY -+ WINDOW_WIDTH = 800; -+ WINDOW_HEIGHT = 450; ++ err(1, "Could not connect to display server"); + + display_create_window(connection, WINDOW_ID); -+ display_resize_window(connection, WINDOW_ID, WINDOW_WIDTH, WINDOW_HEIGHT); -+ display_show_window(connection, WINDOW_ID); -+#endif + -+ for ( int i = 1; i < argc; i++ ) ++ for ( int i = optind; i < argc; i++ ) + { -+#ifdef DISPLAY + display_title_window(connection, WINDOW_ID, argv[i]); -+#endif -+ if ( !PlayVideo(argv[i], connection) ) ++ if ( !play_video(argv[i], connection) ) + return 1; + } + -+#ifdef DISPLAY + display_disconnect(connection); -+#else -+ dispd_destroy_window(window); -+ dispd_detach_session(session); -+#endif + + return 0; +} diff --git a/ports/video-player/video-player.port b/ports/video-player/video-player.port index 485ac491..2d215675 100644 --- a/ports/video-player/video-player.port +++ b/ports/video-player/video-player.port @@ -1,3 +1,4 @@ NAME=video-player BUILD_LIBRARIES=libavcodec BUILD_SYSTEM=sortix-usual-makefile +LICENSE=ISC