Projects
Multimedia
nordlicht
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 22
View file
nordlicht.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Tue Mar 31 18:30:21 UTC 2020 - Olaf Hering <olaf@aepfle.de> + +- Bump to v0.4.5 + +------------------------------------------------------------------- Sat Oct 08 11:36:17 UTC 2016 - joerg.lorenzen@ki.tng.de - Removed service file because build often fails with 'bad temdir'
View file
nordlicht.spec
Changed
@@ -1,23 +1,24 @@ %define soname 0 Name: nordlicht -Version: %{soname}.4.4 +Version: 0.4.5 Release: 0 License: GPL-2.0+ Summary: Creates colorful barcodes from video files Url: https://nordlicht.github.io Group: Productivity/Multimedia/Editors and Convertors -Source0: https://github.com/nordlicht/%{name}/archive/%{name}-%{version}.tar.gz +Source0: %{name}-%{version}.tar.xz BuildRequires: cmake BuildRequires: help2man BuildRequires: pkg-config -BuildRequires: pkgconfig(libavcodec) = 56.60.100 -BuildRequires: pkgconfig(libavformat) = 56.40.101 -BuildRequires: pkgconfig(libavutil) = 54.31.100 -BuildRequires: pkgconfig(libswscale) = 3.1.101 +BuildRequires: pkgconfig(libavcodec) +BuildRequires: pkgconfig(libavformat) +BuildRequires: pkgconfig(libavutil) +BuildRequires: pkgconfig(libswscale) BuildRequires: popt-devel +Requires: lib%{name}%{soname} = %{version}-%{release} ExclusiveArch: %ix86 x86_64 %description @@ -44,8 +45,7 @@ %package devel Summary: Development files for nordlicht Group: Development/Libraries/C and C++ -Requires: lib%{name}%{soname} >= %{version} -Provides: pkgconfig(nordlicht) +Requires: lib%{name}%{soname} = %{version}-%{release} %description devel This package contains all necessary include files and @@ -56,29 +56,24 @@ %setup -q %build -cmake . \ - -DCMAKE_C_FLAGS:STRING="%{optflags}" \ - -DCMAKE_INSTALL_PREFIX:PATH=%{_prefix} \ - -DLIB_INSTALL_DIR:PATH=%{_libdir} -make %{?_smp_mflags} +CFLAGS='%{optflags} -Wno-deprecated-declarations' +%cmake +%cmake_build %install -%make_install +%cmake_install %post -n lib%{name}%{soname} -p /sbin/ldconfig %postun -n lib%{name}%{soname} -p /sbin/ldconfig %files -%defattr(-,root,root) -%doc %{_mandir}/man1/%{name}.1%{ext_man} +%{_mandir}/man1/%{name}.1%{ext_man} %{_bindir}/%{name} %files -n lib%{name}%{soname} -%defattr(-,root,root) %{_libdir}/lib%{name}.so.%{version} %files devel -%defattr(-,root,root) %{_libdir}/lib%{name}.so %{_libdir}/lib%{name}.so.%{soname} %{_libdir}/pkgconfig/%{name}.pc
View file
_service
Added
@@ -0,0 +1,17 @@ +<services> + <service name="tar_scm" mode="disabled"> + <param name="filename">nordlicht</param> + <param name="revision">7ad3f008afe803037b332822028faed64b1751bd</param> + <param name="scm">git</param> + <param name="submodules">disable</param> + <param name="url">https://github.com/nordlicht/nordlicht.git</param> + <param name="versionformat">@PARENT_TAG@</param> + <param name="versionrewrite-pattern">[v]?([^+]+)(.*)</param> + <param name="versionrewrite-replacement">\1</param> + </service> + <service name="recompress" mode="disabled"> + <param name="file">*.tar</param> + <param name="compression">xz</param> + </service> + <service name="set_version" mode="disabled"/> +</services>
View file
nordlicht-0.4.4.tar.gz/.gitignore
Deleted
@@ -1,18 +0,0 @@ -# Build products -CMakeCache.txt -CMakeFiles/ -cmake_install.cmake -CTestTestfile.cmake -libnordlicht.so -libnordlicht.so.* -Makefile -nordlicht -nordlicht.1 -nordlicht.pc -testsuite -version.h - -# Testing -test_tmp_* -video.mp4 -*.png
View file
nordlicht-0.4.4.tar.gz/image.c
Deleted
@@ -1,286 +0,0 @@ -#include "image.h" -#include "error.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <libswscale/swscale.h> - -#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) -#define av_frame_alloc avcodec_alloc_frame -#define av_frame_free av_freep -void av_frame_get_buffer(AVFrame *frame, int magic) { avpicture_alloc((AVPicture *)frame, frame->format, frame->width, frame->height); } -void av_frame_copy(AVFrame *dst, AVFrame *src) { memcpy(dst->data[0], src->data[0], sizeof(uint8_t)*avpicture_get_size(PIX_FMT_RGB24, dst->width, dst->height)); } -#endif - -#define MAX_FILTER_SIZE 256 - -struct image { - AVFrame *frame; -}; - -image *image_init(const int width, const int height) { - image *i; - i = (image *) malloc(sizeof(image)); - - i->frame = (AVFrame *) av_frame_alloc(); - i->frame->width = width; - i->frame->height = height; - i->frame->format = PIX_FMT_RGB24; // best choice? - av_frame_get_buffer(i->frame, 16); // magic number? - return i; -} - -int image_width(const image *i) { - return i->frame->width; -} - -int image_height(const image *i) { - return i->frame->height; -} - -void image_set(const image *i, const int x, const int y, const unsigned char r, const unsigned char g, const unsigned char b) { - *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+0) = r; - *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+1) = g; - *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+2) = b; -} - -unsigned char image_get_r(const image *i, const int x, const int y) { - return *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+0); -} - -unsigned char image_get_g(const image *i, const int x, const int y) { - return *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+1); -} - -unsigned char image_get_b(const image *i, const int x, const int y) { - return *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+2); -} - -void image_to_bgra(unsigned char *target, const int width, const int height, const image *i, const int offset_x, const int offset_y) { - int x, y; - for (y = 0; y < image_height(i) && offset_y+y < height ; y++) { - for (x = 0; x < image_width(i) && offset_x+x < width; x++) { - *(target+width*4*(offset_y+y)+4*(offset_x+x)+0) = image_get_b(i, x, y); - *(target+width*4*(offset_y+y)+4*(offset_x+x)+1) = image_get_g(i, x, y); - *(target+width*4*(offset_y+y)+4*(offset_x+x)+2) = image_get_r(i, x, y); - *(target+width*4*(offset_y+y)+4*(offset_x+x)+3) = 255; - } - } -} - -image *image_from_bgra(const unsigned char *source, const int width, const int height) { - image *i = image_init(width, height); - int x, y; - for (y = 0; y < image_height(i); y++) { - for (x = 0; x < image_width(i); x++) { - image_set(i, x, y, *(source+width*4*y+4*x+2), *(source+width*4*y+4*x+1), *(source+width*4*y+4*x+0)); - } - } - return i; -} - -image* image_clone(const image *i) { - image *i2 = image_init(image_width(i), image_height(i)); - av_frame_copy(i2->frame, i->frame); - return i2; -} - -void image_copy_avframe(const image *i, AVFrame *frame) { - av_frame_copy(i->frame, frame); -} - -image* image_dumb_scale(const image *i, const int width, const int height) { - image *i2 = image_init(width, height); - - float x_factor = 1.0*image_width(i)/width; - float y_factor = 1.0*image_height(i)/height; - - int x, y; - for (x = 0; x < width; x++) { - int x_lower = x_factor*x + 0.5; - int x_upper = x_factor*(x+1) - 0.5; - - if (x_lower > x_upper) { - // this can happen when upscaling. pick nearest-neighbour entry - x_lower = x_upper = x_factor*(x+0.5); - } - - for (y = 0; y < height; y++) { - int y_lower = y_factor*y + 0.5; - int y_upper = y_factor*(y+1) - 0.5; - - if (y_lower > y_upper) { - // this can happen when upscaling. pick nearest-neighbour entry - y_lower = y_upper = y_factor*(y+0.5); - } - - int rsum = 0; - int gsum = 0; - int bsum = 0; - int xx, yy; - for (xx = x_lower; xx <= x_upper; xx++) { - for (yy = y_lower; yy <= y_upper; yy++) { - rsum += image_get_r(i, xx, yy); - gsum += image_get_g(i, xx, yy); - bsum += image_get_b(i, xx, yy); - } - } - int n = (x_upper-x_lower+1)*(y_upper-y_lower+1); - image_set(i2, x, y, rsum/n, gsum/n, bsum/n); - } - } - - return i2; -} - -image* image_scale(const image *i, int width, int height) { - int target_width = width; - int target_height = height; - - if (width == image_width(i) && height == image_height(i)) { - return image_clone(i); - } - - image *i2 = NULL; - image *tmp = (image *) i; - do { - width = target_width; - height = target_height; - -#if LIBSWSCALE_VERSION_MICRO < 100 || LIBSWSCALE_VERSION_INT < AV_VERSION_INT(2, 1, 103) - if (width < 8) { - // libav and old FFmpeg versions don't allow scaling to a width of less than 8 - if (image_width(tmp) > 8) { - // but we can use it to go down to 8 - width = 8; - } else { - // all hope ist lost - image *i3 = image_dumb_scale(tmp, width, height); - if (tmp != i) { - image_free(tmp); - } - return i3; - } - } - - if (height < 2) { - // This doesn't seem to work on libav... - if (image_height(tmp) > 2) { - height = 2; - } else { - image *i3 = image_dumb_scale(tmp, width, height); - if (tmp != i) { - image_free(tmp); - } - return i3; - } - } -#endif - - // When scaling from a high width directly to 1, FFmpeg sometimes (?) - // introduces noise. So we avoid this situation. - if (width == 1 && image_width(tmp) > 2) { - width = 2; - } - - if (image_width(tmp)/width > MAX_FILTER_SIZE) { - width = image_width(tmp)/MAX_FILTER_SIZE+1; - } - if (image_height(tmp)/height > MAX_FILTER_SIZE) { - height = image_height(tmp)/MAX_FILTER_SIZE+1; - } - - - i2 = image_init(width, height); - - struct SwsContext *sws_context = sws_getContext(image_width(tmp), image_height(tmp), tmp->frame->format, - image_width(i2), image_height(i2), i2->frame->format, - SWS_AREA, NULL, NULL, NULL); - sws_scale(sws_context, (uint8_t const * const *)tmp->frame->data,
View file
nordlicht-0.4.4.tar.gz/main.c
Deleted
@@ -1,298 +0,0 @@ -#include <pthread.h> -#include <sys/file.h> -#include <sys/mman.h> -#include <stdarg.h> -#include <unistd.h> -#include <string.h> -#include <popt.h> -#include "nordlicht.h" -#include "version.h" - -#ifdef _WIN32 -// from http://stackoverflow.com/a/8514474/248734 -char* strsep(char** stringp, const char* delim) { - char* start = *stringp; - char* p; - - p = (start != NULL) ? strpbrk(start, delim) : NULL; - - if (p == NULL) { - *stringp = NULL; - } else { - *p = '\0'; - *stringp = p + 1; - } - - return start; -} -#endif - -typedef struct { - const char *name; - const char *description; - nordlicht_style style; -} style; - -const style style_table[] = { - {"horizontal", "compress frames to vertical lines and append them", NORDLICHT_STYLE_HORIZONTAL}, - {"vertical", "compress frames to horizontal lines and rotate them counterclockwise by 90 degrees", NORDLICHT_STYLE_VERTICAL}, - {"slitscan", "take single columns while constantly moving to the right (and wrapping back to the left)", NORDLICHT_STYLE_SLITSCAN}, - {"middlecolumn", "take the middlemost column of each frame", NORDLICHT_STYLE_MIDDLECOLUMN}, - {"thumbnails", "display small thumbnails at regular intervals", NORDLICHT_STYLE_THUMBNAILS}, - {"spectrogram", "spectrogram of the first audio track (not all sample formats are supported yet)", NORDLICHT_STYLE_SPECTROGRAM}, - {NULL, NULL, NORDLICHT_STYLE_LAST} -}; - -void print_error(const char *message, ...) { - fprintf(stderr, "nordlicht: "); - va_list arglist; - va_start(arglist, message); - vfprintf(stderr, message, arglist); - va_end(arglist); - fprintf(stderr, "\n"); -} - -const char *filename_ext(const char *path) { - const char *dot = strrchr(path, '.'); - if (!dot || dot == path) return ""; - return dot+1; -} - -void print_help(const poptContext popt, const int ret) { - poptPrintHelp(popt, ret == 0 ? stdout : stderr, 0); - - printf("\nStyles:\n"); - int i; - for (i = 0; style_table[i].name; i++) { - printf(" %-14s %s\n", style_table[i].name, style_table[i].description); - } - - printf("\n\ -Examples:\n\ - nordlicht video.mp4 generate video.mp4.png of 1000 x 100 pixels size\n\ - nordlicht video.mp4 --style=vertical compress individual frames to columns\n\ - nordlicht video.mp4 -w 1920 -h 200 -o barcode.png override size and name of the output file\n"); - - exit(ret); -} - -int main(const int argc, const char **argv) { - int width = -1; - int height = -1; - float start = 0.0; - float end = 1.0; - char *output_file = NULL; - char *styles_string = NULL; - nordlicht_strategy strategy; - int free_output_file = 0; - - int quiet = 0; - int help = 0; - int version = 0; - - const struct poptOption optionsTable[] = { - {"width", 'w', POPT_ARG_INT, &width, 0, "set the barcode's width; by default it's \"height*10\", or 1920 pixels, if both are undefined", NULL}, - {"height", 'h', POPT_ARG_INT, &height, 0, "set the barcode's height; by default it's \"width/10\"", NULL}, - {"output", 'o', POPT_ARG_STRING, &output_file, 0, "set output filename, the default is VIDEOFILE.png; when you specify an *.bgra file, you'll get a raw 32-bit BGRA file that is updated as the barcode is generated", "FILENAME"}, - {"style", 's', POPT_ARG_STRING, &styles_string, 0, "default is 'horizontal', see \"Styles\" section below. You can specify more than one style, separated by '+', to get multiple tracks", "STYLE"}, - {"start", '\0', POPT_ARG_FLOAT, &start, 0, "specify where to start the barcode (in percent between 0 and 1)", NULL}, - {"end", '\0', POPT_ARG_FLOAT, &end, 0, "specify where to end the barcode (in percent between 0 and 1)", NULL}, - {"quiet", 'q', 0, &quiet, 0, "don't show progress indicator", NULL}, - {"help", '\0', 0, &help, 0, "display this help and exit", NULL}, - {"version", '\0', 0, &version, 0, "output version information and exit", NULL}, - POPT_TABLEEND - }; - - const poptContext popt = poptGetContext(NULL, argc, argv, optionsTable, 0); - poptSetOtherOptionHelp(popt, "[OPTION]... VIDEOFILE\n\nOptions:"); - - char c; - - // The next line leaks 3 bytes, blame popt! - while ((c = poptGetNextOpt(popt)) >= 0) { } - - if (c < -1) { - fprintf(stderr, "nordlicht: %s: %s\n", poptBadOption(popt, POPT_BADOPTION_NOALIAS), poptStrerror(c)); - return 1; - } - - if (version) { - printf("nordlicht %s\n\nWritten by Sebastian Morr and contributors.\n", NORDLICHT_VERSION); - return 0; - } - - if (help) { - print_help(popt, 0); - } - - const char *filename = (char*)poptGetArg(popt); - - if (filename == NULL) { - print_error("Please specify an input file."); - exit(1); - } - - if (poptGetArg(popt) != NULL) { - print_error("Please specify only one input file."); - exit(1); - } - - if (output_file == NULL) { - size_t len = snprintf(NULL, 0, "%s.nordlicht.png", filename) + 1; - output_file = (char *) malloc(len); - snprintf(output_file, len, "%s.nordlicht.png", filename); - free_output_file = 1; - } - - if (width == -1 && height != -1) { - width = height*10; - } - if (height == -1 && width != -1) { - height = width/10; - if (height < 1) { - height = 1; - } - } - if (height == -1 && width == -1) { - width = 1920; - height = 192; - } - - if (styles_string == NULL) { - styles_string = "horizontal"; - } - - // count the occurrences of "+" in the styles_string - const char *s = styles_string; - int num_tracks; - for (num_tracks=0; s[num_tracks]; s[num_tracks]=='+' ? num_tracks++ : *s++); - num_tracks++; - - nordlicht_style *styles; - styles = (nordlicht_style *) malloc(num_tracks * sizeof(nordlicht_style)); - - const char *style_string; - num_tracks = 0; - while ((style_string = strsep(&styles_string, "+"))) { - int i; - for (i = 0; style_table[i].name; i++) { - if (strcmp(style_string, style_table[i].name) == 0) { - styles[num_tracks] = style_table[i].style; - break; - } - } - - if (!style_table[i].name) { - print_error("Unknown style '%s'. Use '--help' to display available styles.", style_string); - exit(1); - } - num_tracks++; - } - - const char *ext = filename_ext(output_file); - if (strcmp(ext, "png") == 0) { - strategy = NORDLICHT_STRATEGY_FAST; - } else if (strcmp(ext, "bgra") == 0) { - strategy = NORDLICHT_STRATEGY_LIVE; - } else { - print_error("Unsupported file extension '%s'.", ext); - exit(1);
View file
nordlicht-0.4.4.tar.gz/nordlicht.c
Deleted
@@ -1,331 +0,0 @@ -#include "nordlicht.h" -#include <string.h> -#include "error.h" -#include "source.h" - -#ifdef _WIN32 -#define realpath(N,R) _fullpath((R),(N),_MAX_PATH) -#endif - -typedef struct { - nordlicht_style style; - int height; -} track; - -struct nordlicht { - int width, height; - const char *filename; - track *tracks; - int num_tracks; - unsigned char *data; - - int owns_data; - int modifiable; - nordlicht_strategy strategy; - float progress; - source *source; -}; - -NORDLICHT_API size_t nordlicht_buffer_size(const nordlicht *n) { - return n->width * n->height * 4; -} - -NORDLICHT_API nordlicht* nordlicht_init(const char *filename, const int width, const int height) { - if (width < 1 || height < 1) { - error("Dimensions must be positive (got %dx%d)", width, height); - return NULL; - } - nordlicht *n; - n = (nordlicht *) malloc(sizeof(nordlicht)); - - n->width = width; - n->height = height; - n->filename = filename; - - n->data = (unsigned char *) calloc(nordlicht_buffer_size(n), 1); - if (n->data == 0) { - error("Not enough memory to allocate %d bytes", nordlicht_buffer_size(n)); - return NULL; - } - - n->owns_data = 1; - - n->num_tracks = 1; - n->tracks = (track *) malloc(sizeof(track)); - n->tracks[0].style = NORDLICHT_STYLE_HORIZONTAL; - n->tracks[0].height = n->height; - - n->strategy = NORDLICHT_STRATEGY_FAST; - n->modifiable = 1; - n->progress = 0; - n->source = source_init(filename); - - if (n->source == NULL) { - error("Could not open video file '%s'", filename); - free(n); - return NULL; - } - - return n; -} - -NORDLICHT_API void nordlicht_free(nordlicht *n) { - if (n->owns_data) { - free(n->data); - } - free(n->tracks); - source_free(n->source); - free(n); -} - -NORDLICHT_API const char *nordlicht_error() { - return get_error(); -} - -NORDLICHT_API int nordlicht_set_start(nordlicht *n, const float start) { - if (! n->modifiable) { - return -1; - } - - if (start < 0) { - error("'start' has to be >= 0."); - return -1; - } - - if (start >= source_end(n->source)) { - error("'start' has to be smaller than 'end'."); - return -1; - } - - source_set_start(n->source, start); - return 0; -} - -NORDLICHT_API int nordlicht_set_end(nordlicht *n, const float end) { - if (! n->modifiable) { - return -1; - } - - if (end > 1) { - error("'end' has to be <= 1."); - return -1; - } - - if (source_start(n->source) >= end) { - error("'start' has to be smaller than 'end'."); - return -1; - } - - source_set_end(n->source, end); - return 0; -} - -NORDLICHT_API int nordlicht_set_style(nordlicht *n, const nordlicht_style style) { - if (! n->modifiable) { - return -1; - } - - nordlicht_style styles[1] = {style}; - return nordlicht_set_styles(n, styles, 1); -} - -NORDLICHT_API int nordlicht_set_styles(nordlicht *n, const nordlicht_style *styles, const int num_tracks) { - if (! n->modifiable) { - return -1; - } - - n->num_tracks = num_tracks; - - if (n->num_tracks > n->height) { - error("Height of %d px is too low for %d styles", n->height, n->num_tracks); - return -1; - } - - free(n->tracks); - n->tracks = (track *) malloc(n->num_tracks*sizeof(track)); - - int height_of_each_track = n->height/n->num_tracks; - int i; - for (i=0; i<num_tracks; i++) { - nordlicht_style s = styles[i]; - if (s > NORDLICHT_STYLE_LAST-1) { - return -1; - } - - n->tracks[i].style = s; - n->tracks[i].height = height_of_each_track; - } - n->tracks[0].height = n->height - (n->num_tracks-1)*height_of_each_track; - - return 0; -} - -NORDLICHT_API int nordlicht_set_strategy(nordlicht *n, const nordlicht_strategy s) { - if (! n->modifiable) { - return -1; - } - if (s > NORDLICHT_STRATEGY_LIVE) { - return -1; - } - n->strategy = s; - return 0; -} - -NORDLICHT_API int nordlicht_generate(nordlicht *n) { - n->modifiable = 0; - - source_build_keyframe_index(n->source, n->width); - - int x, exact; - - const int do_a_fast_pass = (n->strategy == NORDLICHT_STRATEGY_LIVE) || !source_exact(n->source); - const int do_an_exact_pass = source_exact(n->source); - - for (exact = (!do_a_fast_pass); exact <= do_an_exact_pass; exact++) { - int i; - int y_offset = 0; - for(i = 0; i < n->num_tracks; i++) { - // call this for each track, to seek to the beginning - source_set_exact(n->source, exact); - - for (x = 0; x < n->width; x++) { - image *frame; - - if (n->tracks[i].style == NORDLICHT_STYLE_SPECTROGRAM) { - if (!source_has_audio(n->source)) { - error("File contains no audio, please select an appropriate style"); - n->progress = 1; - return -1; - }
View file
nordlicht-0.4.4.tar.gz/nordlicht.h
Deleted
@@ -1,101 +0,0 @@ -#ifndef INCLUDE_nordlicht_h__ -#define INCLUDE_nordlicht_h__ -#include <stdlib.h> // for size_t - - -#ifndef NORDLICHT_API -# ifdef _WIN32 -# if defined(NORDLICHT_BUILD_SHARED) /* build dll */ -# define NORDLICHT_API __declspec(dllexport) -# elif !defined(NORDLICHT_BUILD_STATIC) /* use dll */ -# define NORDLICHT_API __declspec(dllimport) -# else /* static library */ -# define NORDLICHT_API -# endif -# else -# if __GNUC__ >= 4 -# define NORDLICHT_API __attribute__((visibility("default"))) -# else -# define NORDLICHT_API -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct nordlicht nordlicht; - -typedef enum nordlicht_style { - NORDLICHT_STYLE_THUMBNAILS, - NORDLICHT_STYLE_HORIZONTAL, // compress frames to columns, "move to the right" - NORDLICHT_STYLE_VERTICAL, // compress frames to rows, "move downwards" - NORDLICHT_STYLE_SLITSCAN, // take single columns, while moving to the right (and wrapping to the left) - NORDLICHT_STYLE_MIDDLECOLUMN, // take the frames' middlemost column - NORDLICHT_STYLE_SPECTROGRAM, // spectrogram of the first audio track (not all sample formats are supported yet) - NORDLICHT_STYLE_LAST -} nordlicht_style; - -typedef enum nordlicht_strategy { - NORDLICHT_STRATEGY_FAST, // generate barcode in a single pass as fast as possible - NORDLICHT_STRATEGY_LIVE, // generate a fast approximation first, good for live display -} nordlicht_strategy; - -// Returns a description of the last error, or NULL if the was no error. -NORDLICHT_API const char *nordlicht_error(); - -// Allocate a new nordlicht of specific width and height, for a given video -// file. When `live` is true, give a fast approximation before starting the -// slow, exact generation. Use `nordlicht_free` to free the nordlicht again. -// Returns NULL on errors. -NORDLICHT_API nordlicht* nordlicht_init(const char *filename, const int width, const int height); - -// Free a nordlicht. -NORDLICHT_API void nordlicht_free(nordlicht *n); - -// Specify where to start the nordlicht, in percent between 0 and 1. -NORDLICHT_API int nordlicht_set_start(nordlicht *n, const float start); - -// Specify where to end the nordlicht, in percent between 0 and 1. -NORDLICHT_API int nordlicht_set_end(nordlicht *n, const float end); - -// Set the output style of the nordlicht. Default is NORDLICHT_STYLE_HORIZONTAL. -// Returns 0 on success. To set multiple styles at once, use `nordlicht_set_styles`. -NORDLICHT_API int nordlicht_set_style(nordlicht *n, const nordlicht_style style); - -// Set multiple output styles, which will be displayed on top of each other. -// Expects a pointer to an array of nordlicht_style-s of length `num_styles`. -// Returns 0 on success. -NORDLICHT_API int nordlicht_set_styles(nordlicht *n, const nordlicht_style *styles, const int num_styles); - -// Set the generation strategy of the nordlicht. Default is NORDLICHT_STRATEGY_FAST. -// Returns 0 on success. This function will be removed in the future. -NORDLICHT_API int nordlicht_set_strategy(nordlicht *n, const nordlicht_strategy strategy); - -// Returns a pointer to the nordlicht's internal buffer. You can use it to draw -// the barcode while it is generated. The pixel format is 32-bit BGRA. -NORDLICHT_API const unsigned char* nordlicht_buffer(const nordlicht *n); - -// Replace the internal nordlicht's internal buffer. The data pointer is owned -// by the caller and must be freed after `nordlicht_free`. Returns 0 on success. -NORDLICHT_API int nordlicht_set_buffer(nordlicht *n, unsigned char *data); - -// Returns the size of this nordlicht's buffer in bytes. -NORDLICHT_API size_t nordlicht_buffer_size(const nordlicht *n); - -// Generate the nordlicht. Calling this will freeze the nordlicht: -// "set" functions will fail. Returns 0 on success. -NORDLICHT_API int nordlicht_generate(nordlicht *n); - -// Returns a value between 0 and 1 indicating how much of the nordlicht is done. -NORDLICHT_API float nordlicht_progress(const nordlicht *n); - -// Write the nordlicht to a PNG file. Returns 0 on success. -NORDLICHT_API int nordlicht_write(const nordlicht *n, const char *filename); - -#ifdef __cplusplus -} -#endif - -#endif
View file
nordlicht-0.4.4.tar.gz/source.c
Deleted
@@ -1,467 +0,0 @@ -#include "source.h" -#include "error.h" -#include <libavcodec/avcodec.h> -#include <libavcodec/avfft.h> -#include <libavformat/avformat.h> -#include <libavutil/avutil.h> -#include <libswscale/swscale.h> - -#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) -#define av_frame_alloc avcodec_alloc_frame -#define av_frame_free av_freep -#endif - -#define HEURISTIC_NUMBER_OF_FRAMES 1800 // how many frames will the heuristic look at? -#define HEURISTIC_KEYFRAME_FACTOR 1 // lower bound for the actual/required keyframe ratio - -#define SAMPLES_PER_FRAME 1024 - -typedef struct { - int stream; - AVCodecContext *codec; - image *last_frame; - - double time_base; - double fps; - AVFrame *frame; - long current_frame; -} stream; - -struct source { - int exact; - float start, end; - - AVFormatContext *format; - stream *video; - stream *audio; - - uint8_t *buffer; - AVFrame *scaleframe; - struct SwsContext *sws_context; - AVPacket packet; - - // audio specific - RDFTContext *rdft; - - int *keyframes; - int number_of_keyframes; - int has_index; -}; - -long packet_pts(stream *st, const AVPacket *packet) { - long pts = packet->pts != 0 ? packet->pts : packet->dts; - double sec = st->time_base*pts; - return (int64_t)(st->fps*sec + 0.5); -} - -int grab_next_frame(source *s, stream *st) { - int valid = 0; - int got_frame = 0; - - long pts; - - while (!valid) { - if (av_read_frame(s->format, &s->packet) >= 0) { - if (s->packet.stream_index == st->stream) { - switch (st->codec->codec_type) { - case AVMEDIA_TYPE_VIDEO: - avcodec_decode_video2(st->codec, st->frame, &got_frame, &s->packet); - break; - case AVMEDIA_TYPE_AUDIO: - avcodec_decode_audio4(st->codec, st->frame, &got_frame, &s->packet); - break; - default: - error("Stream has unknown media type."); - return 1; - } - - if (got_frame) { - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - if (st->frame->data[0] == 0) { - return 1; - } - } - pts = packet_pts(st, &s->packet); - valid = 1; - } - } - av_free_packet(&s->packet); - } else { - av_free_packet(&s->packet); - st->current_frame = -1; - return 1; - } - } - - av_free_packet(&s->packet); - st->current_frame = pts; - return 0; -} - -int seek_keyframe(source *s, stream *st, const long frame) { - av_seek_frame(s->format, st->stream, frame/st->fps/st->time_base, AVSEEK_FLAG_BACKWARD); - avcodec_flush_buffers(st->codec); - return grab_next_frame(s, st) != 0; -} - -int total_number_of_frames(const source *s, stream *st) { - double duration_sec = 1.0*s->format->duration/AV_TIME_BASE; - return st->fps*duration_sec; -} - -void source_build_keyframe_index(source *s, const int width) { - if (! s->video) { - return; - } - - s->keyframes = (int *) malloc(sizeof(long)*60*60*3); // TODO: dynamic datastructure! - s->number_of_keyframes = 0; - - int frame = 0; - - s->has_index = 0; - s->exact = 1; - seek_keyframe(s, s->video, 0); - - while (av_read_frame(s->format, &s->packet) >= 0) { - if (s->packet.stream_index == s->video->stream) { - if (!!(s->packet.flags & AV_PKT_FLAG_KEY)) { - s->number_of_keyframes++; - - long pts = packet_pts(s->video, &s->packet); - if (pts < 1 && s->number_of_keyframes > 0) { - pts = frame; - } - - s->keyframes[s->number_of_keyframes] = pts; - } - if (frame == HEURISTIC_NUMBER_OF_FRAMES) { - const float density = 1.0*s->number_of_keyframes/HEURISTIC_NUMBER_OF_FRAMES; - const float required_density = 1.0*HEURISTIC_KEYFRAME_FACTOR/COLUMN_PRECISION*width/total_number_of_frames(s, s->video)/(s->end-s->start); - if (density > required_density) { - // The keyframe density in the first `HEURISTIC_NUMBER_OF_FRAMES` - // frames is HEURISTIC_KEYFRAME_FACTOR times higher than - // the density we need overall. - s->exact = 0; - av_free_packet(&s->packet); - return; - } - } - frame++; - } - av_free_packet(&s->packet); - } - av_free_packet(&s->packet); - s->has_index = 1; -} - -stream* stream_init(source *s, enum AVMediaType type) { - stream *st; - st = (stream *) malloc(sizeof(stream)); - - st->last_frame = NULL; - - st->stream = av_find_best_stream(s->format, type, -1, -1, NULL, 0); - if (st->stream < 0) { - free(st); - return NULL; - } - st->codec = s->format->streams[st->stream]->codec; - AVCodec *codec = NULL; - codec = avcodec_find_decoder(st->codec->codec_id); - if (codec == NULL) { - error("Unsupported codec!"); - free(st); - return NULL; - } - if (avcodec_open2(st->codec, codec, NULL) < 0) { - free(st); - return NULL; - } - - st->time_base = av_q2d(s->format->streams[st->stream]->time_base); - - switch (st->codec->codec_type) { - case AVMEDIA_TYPE_VIDEO: - st->fps = av_q2d(s->format->streams[st->stream]->avg_frame_rate); - break; - case AVMEDIA_TYPE_AUDIO: - st->fps = st->codec->sample_rate; - break; - default: - error("Stream has unknown media type."); - free(st); - return NULL; - } - - st->frame = av_frame_alloc(); - st->current_frame = -1; -
View file
nordlicht-0.4.4.tar.gz/source.h
Deleted
@@ -1,37 +0,0 @@ -#ifndef INCLUDE_source_h__ -#define INCLUDE_source_h__ - -#include "nordlicht.h" -#include "image.h" - -#define COLUMN_PRECISION 0.95 // choose a frame from this percentage at the middle of each column - -typedef struct source source; - -source* source_init(const char *filename); - -int source_has_video(source *s); - -int source_has_audio(source *s); - -image* source_get_video_frame(source *s, const double min_percent, const double max_percent); - -image* source_get_audio_frame(source *s, const double min_percent, const double max_percent); - -void source_build_keyframe_index(source *s, const int width); - -int source_exact(const source *s); - -void source_set_exact(source *s, const int exact); - -float source_start(const source *s); - -void source_set_start(source *s, const float start); - -float source_end(const source *s); - -void source_set_end(source *s, const float end); - -void source_free(source *s); - -#endif
View file
nordlicht-0.4.4.tar.gz/testsuite.c
Deleted
@@ -1,199 +0,0 @@ -#include "cheat.h" -#include "nordlicht.h" - -#ifdef _WIN32 -#include <io.h> -#define F_OK 0 -#define access _access -#endif - -#define cheat_null(x) cheat_assert(NULL == (x)) -#define cheat_not_null(x) cheat_assert(NULL != (x)) -#define cheat_fail(x) cheat_assert(0 != (x)) -#define cheat_ok(x) cheat_assert(0 == (x)) - -CHEAT_DECLARE( - nordlicht *n; - - int tool(char *args) { - char c[200]; - snprintf(c, 200, "./nordlicht %s >/dev/null 2>/dev/null", args); - return system(c); - } -) - -CHEAT_SET_UP( - n = NULL; -) - -CHEAT_TEAR_DOWN( - if (n != NULL) { - nordlicht_free(n); - } -) - -CHEAT_TEST(testfile_exists, - cheat_assert(-1 != access("video.mp4", F_OK)); -) - -CHEAT_TEST(invalid_input_file, - cheat_null(nordlicht_init(NULL, 100, 100)); - cheat_null(nordlicht_init("", 100, 100)); - cheat_null(nordlicht_init("\0", 100, 100)); - cheat_null(nordlicht_init(".", 100, 100)); - cheat_null(nordlicht_init("..", 100, 100)); - cheat_null(nordlicht_init("nonexistent_file.123", 100, 100)); -) - -CHEAT_TEST(invalid_size, - cheat_null(nordlicht_init("video.mp4", 0, 100)); - cheat_null(nordlicht_init("video.mp4", 100, 0)); - cheat_null(nordlicht_init("video.mp4", 0, 0)); - cheat_null(nordlicht_init("video.mp4", -1, 1)); - cheat_null(nordlicht_init("video.mp4", 1, -1)); - cheat_null(nordlicht_init("video.mp4", -100, 100)); - cheat_null(nordlicht_init("video.mp4", 100, -100)); - cheat_null(nordlicht_init("video.mp4", INT_MIN, INT_MIN)); -) - - -CHEAT_TEST(valid_size, - cheat_not_null(nordlicht_init("video.mp4", 1, 1)); - cheat_not_null(nordlicht_init("video.mp4", INT_MAX, INT_MAX)); -) - -CHEAT_TEST(invalid_output, - n = nordlicht_init("video.mp4", 1, 100); - cheat_not_null(n); - cheat_fail(nordlicht_write(n, NULL)); - cheat_fail(nordlicht_write(n, "")); - cheat_fail(nordlicht_write(n, "\0")); - cheat_fail(nordlicht_write(n, ".")); - cheat_fail(nordlicht_write(n, "..")); - cheat_fail(nordlicht_write(n, "video.mp4")); -) - -CHEAT_TEST(style, - n = nordlicht_init("video.mp4", 1, 100); - cheat_not_null(n); - cheat_ok(nordlicht_set_style(n, NORDLICHT_STYLE_HORIZONTAL)); - cheat_ok(nordlicht_set_style(n, NORDLICHT_STYLE_VERTICAL)); - cheat_fail(nordlicht_set_style(n, 10000000)); -) - -CHEAT_TEST(styles, - n = nordlicht_init("video.mp4", 1, 100); - cheat_not_null(n); - nordlicht_style styles[2]; - styles[0] = NORDLICHT_STYLE_HORIZONTAL; - styles[1] = NORDLICHT_STYLE_VERTICAL; - cheat_ok(nordlicht_set_styles(n, styles, 2)); - styles[0] = NORDLICHT_STYLE_THUMBNAILS; - cheat_ok(nordlicht_set_styles(n, styles, 2)); - styles[0] = 10000000; - cheat_fail(nordlicht_set_styles(n, styles, 2)); -) - -CHEAT_TEST(strategy, - n = nordlicht_init("video.mp4", 1, 100); - cheat_not_null(n); - cheat_ok(nordlicht_set_strategy(n, NORDLICHT_STRATEGY_FAST)); - cheat_ok(nordlicht_set_strategy(n, NORDLICHT_STRATEGY_LIVE)); - cheat_fail(nordlicht_set_strategy(n, 2)); - cheat_fail(nordlicht_set_strategy(n, 1000000)); - cheat_fail(nordlicht_set_strategy(n, -1)); -) - -CHEAT_TEST(buffer, - const unsigned char *buffer = NULL; - n = nordlicht_init("video.mp4", 2, 100); - cheat_not_null(n); - buffer = nordlicht_buffer(n); - cheat_not_null(buffer); - cheat_assert(2*100*4 == nordlicht_buffer_size(n)); - unsigned char *buffer2 = NULL; - cheat_fail(nordlicht_set_buffer(n, buffer2)); - buffer2 = malloc(nordlicht_buffer_size(n)); - cheat_ok(nordlicht_set_buffer(n, buffer2)); - cheat_ok(nordlicht_set_buffer(n, buffer2)); - cheat_ok(nordlicht_set_buffer(n, buffer2)); - buffer = nordlicht_buffer(n); - cheat_assert(buffer == buffer2); - free(buffer2); -) - -CHEAT_TEST(complete_run, - unsigned char *buffer2 = NULL; - n = nordlicht_init("video.mp4", 1, 100); - cheat_not_null(n); - cheat_ok(nordlicht_progress(n)); - cheat_ok(nordlicht_generate(n)); - cheat_assert(1 == nordlicht_progress(n)); - buffer2 = malloc(nordlicht_buffer_size(n)); - cheat_fail(nordlicht_set_buffer(n, buffer2)); - free(buffer2); -) - -CHEAT_TEST(tool_argument_parsing, - cheat_ok(tool("--help")); - cheat_ok(tool("--version")); - cheat_fail(tool("")); - cheat_fail(tool("--fubar")); - cheat_fail(tool("one.mp4 two.mp4")); - cheat_fail(tool("does_not_exist.mp4")); -) - -CHEAT_TEST(tool_size, - cheat_ok(tool("video.mp4 -w 1 -h 1")); - cheat_ok(tool("video.mp4 -w 1 -h 10000")); - cheat_fail(tool("video.mp4 -w huuuge")); - cheat_fail(tool("video.mp4 -w 0")); - cheat_fail(tool("video.mp4 -h 0")); - cheat_fail(tool("video.mp4 -w ''")); - cheat_fail(tool("video.mp4 -h ''")); - cheat_fail(tool("video.mp4 -w -100")); - cheat_fail(tool("video.mp4 -h -100")); - cheat_fail(tool("video.mp4 -w 1.1")); - cheat_fail(tool("video.mp4 -h 1.1")); - cheat_fail(tool("video.mp4 -w 1,1")); - cheat_fail(tool("video.mp4 -h 1,1")); -) - -CHEAT_TEST(tool_output, - cheat_ok(tool("video.mp4 -w 1")); - cheat_assert(-1 != access("video.mp4.nordlicht.png", F_OK)); - cheat_ok(tool("video.mp4 -w 1 -o ünîç⌀də.png")); - cheat_assert(-1 != access("ünîç⌀də.png", F_OK)); - cheat_fail(tool("video.mp4 -o video.mp4")); - cheat_fail(tool("video.mp4 -o ''")); - cheat_ok(tool("video.mp4 -w 1 -o barcode.bgra")); - cheat_fail(tool("video.mp4 -o barcode.abc")); - cheat_fail(tool("video.mp4 -o barcode")); -) - -CHEAT_TEST(tool_style, - cheat_ok(tool("video.mp4 -w 1 -s vertical")); - cheat_ok(tool("video.mp4 -w 1 -s horizontal")); - cheat_fail(tool("video.mp4 -h 1 -s horizontal+vertical")); - cheat_fail(tool("video.mp4 -h 2 -s horizontal+vertical+horizontal")); - cheat_ok(tool("video.mp4 -h 2 -s horizontal+vertical")); - cheat_fail(tool("video.mp4 -s horizontal+")); - cheat_fail(tool("video.mp4 -s +")); - cheat_fail(tool("video.mp4 -s horizontal++horizontal")); - cheat_fail(tool("video.mp4 -s nope")); - cheat_fail(tool("video.mp4 -s ''")); -) - -CHEAT_TEST(tool_region, - cheat_ok(tool("video.mp4 -w 1 --start=0.5")); - cheat_ok(tool("video.mp4 -w 1 --end=0.5")); - cheat_ok(tool("video.mp4 -w 1 --start=0.1 --end=0.2")); - cheat_ok(tool("video.mp4 -w 1 --start=0 --end=1")); - cheat_fail(tool("video.mp4 -w 1 --start=-1")); - cheat_fail(tool("video.mp4 -w 1 --start=1")); - cheat_fail(tool("video.mp4 -w 1 --start=2")); - cheat_fail(tool("video.mp4 -w 1 --end=-1")); - cheat_fail(tool("video.mp4 -w 1 --end=0")); - cheat_fail(tool("video.mp4 -w 1 --end=2")); - cheat_fail(tool("video.mp4 -w 1 --start=0.2 --end=0.1")); -)
View file
nordlicht-0.4.4.tar.gz/CHANGELOG.md -> nordlicht-0.4.5.tar.xz/CHANGELOG.md
Changed
@@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. *nordlicht* uses [Semantic Versioning](http://semver.org/). +## 0.4.5 - 2017-01-09 + +- introduce `nordlicht_generate_step` and `nordlicht_done` to the API, for simple, non-blocking applications +- improve FFmpeg backwards compability down to v3.0 (thanks, Manuel!) +- fix build on ARM platforms +- correctly open files which contain a colon (thanks, Roland!) +- various bug fixes and stability improvements + +- tool: when the user specifies a non-PNG file as output, warn them but don't fail + ## 0.4.4 - 2016-01-24 - introduce the convention that the nordlicht is always written to `VIDEOFILE.nordlicht.png`
View file
nordlicht-0.4.4.tar.gz/CMakeLists.txt -> nordlicht-0.4.5.tar.xz/CMakeLists.txt
Changed
@@ -3,7 +3,7 @@ project(nordlicht C) set(MAJOR_VERSION 0) set(MINOR_VERSION 4) -set(PATCH_VERSION 4) +set(PATCH_VERSION 5) set(NORDLICHT_VERSION "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}") option (BUILD_SHARED_LIBS "Build shared libraries." ON) @@ -12,6 +12,8 @@ include(GNUInstallDirs) +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") + if (BUILD_SHARED_LIBS) add_definitions(-DNORDLICHT_BUILD_SHARED) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") @@ -20,7 +22,6 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") endif() -find_package(Threads REQUIRED) find_package(FFmpeg COMPONENTS AVUTIL AVFORMAT AVCODEC SWSCALE REQUIRED) find_package(Popt REQUIRED) @@ -33,22 +34,22 @@ include_directories(${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR} ${FFMPEG_INCLUDE_DIRS} ${POPT_INCLUDES}) -add_library(libnordlicht error.c image.c nordlicht.c source.c) +add_library(libnordlicht src/error.c src/image.c src/nordlicht.c src/source.c) set_target_properties(libnordlicht PROPERTIES OUTPUT_NAME nordlicht) set_target_properties(libnordlicht PROPERTIES SOVERSION ${MAJOR_VERSION} VERSION ${NORDLICHT_VERSION}) set_target_properties(libnordlicht PROPERTIES C_VISIBILITY_PRESET hidden) target_link_libraries(libnordlicht m ${FFMPEG_LIBRARIES}) -add_executable(nordlicht main.c) -target_link_libraries(nordlicht libnordlicht ${POPT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) +add_executable(nordlicht src/main.c) +target_link_libraries(nordlicht libnordlicht ${POPT_LIBRARIES}) if (WIN32) target_link_libraries(nordlicht mman) endif() -add_executable(testsuite testsuite.c) +add_executable(testsuite src/testsuite.c) target_link_libraries(testsuite libnordlicht) -configure_file(version.h.in version.h @ONLY) +configure_file(src/version.h.in version.h @ONLY) if (NOT WIN32) configure_file(cmake/nordlicht.pc.in nordlicht.pc @ONLY) @@ -60,10 +61,10 @@ install(TARGETS libnordlicht DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(TARGETS nordlicht DESTINATION bin) -install(FILES nordlicht.h DESTINATION include) +install(FILES ${CMAKE_SOURCE_DIR}/src/nordlicht.h DESTINATION include) if (NOT WIN32) - install(FILES ${CMAKE_BINARY_DIR}/nordlicht.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + install(FILES ${CMAKE_BINARY_DIR}/nordlicht.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) install(FILES ${CMAKE_BINARY_DIR}/nordlicht.1 DESTINATION share/man/man1) endif()
View file
nordlicht-0.4.4.tar.gz/README.md -> nordlicht-0.4.5.tar.xz/README.md
Changed
@@ -21,4 +21,4 @@ ## License: GPLv2+ -See [LICENSE.md] for details. +See [LICENSE.md](LICENSE.md) for details.
View file
nordlicht-0.4.4.tar.gz/cmake/download_testfile.cmake -> nordlicht-0.4.5.tar.xz/cmake/download_testfile.cmake
Changed
@@ -1,4 +1,4 @@ if(NOT EXISTS ${CMAKE_BINARY_DIR}/video.mp4) - message("Downloading 20 MB test file, just a sec...") - file(DOWNLOAD https://upload.wikimedia.org/wikipedia/commons/7/79/Big_Buck_Bunny_small.ogv ${CMAKE_BINARY_DIR}/video.mp4 EXPECTED_MD5 9f701e645fd55e1ae8d35b7671002881) + message("Downloading 3 MB test file, just a sec...") + file(DOWNLOAD https://upload.wikimedia.org/wikipedia/commons/0/07/Sintel_excerpt.OGG ${CMAKE_BINARY_DIR}/video.mp4 EXPECTED_MD5 be22cb1f83f6f3620d8048df12f9f52d) endif()
View file
nordlicht-0.4.5.tar.xz/src
Added
+(directory)
View file
nordlicht-0.4.5.tar.xz/src/cheat.h
Changed
(renamed from cheat.h)
View file
nordlicht-0.4.5.tar.xz/src/error.c
Changed
(renamed from error.c)
View file
nordlicht-0.4.5.tar.xz/src/error.h
Changed
(renamed from error.h)
View file
nordlicht-0.4.5.tar.xz/src/image.c
Added
@@ -0,0 +1,313 @@ +#include "image.h" +#include "error.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libswscale/swscale.h> + +// Changes for ffmpeg 3.0 +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,24,0) +# include <libavutil/imgutils.h> +# define av_free_packet av_packet_unref +# define avpicture_get_size(fmt,w,h) av_image_get_buffer_size(fmt,w,h,1) +#endif + +// PIX_FMT was renamed to AV_PIX_FMT on this version +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,74,100) +# define AVPixelFormat PixelFormat +# define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 +# define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P +# define AV_PIX_FMT_YUVJ422P PIX_FMT_YUVJ422P +# define AV_PIX_FMT_YUVJ440P PIX_FMT_YUVJ440P +# define AV_PIX_FMT_YUVJ444P PIX_FMT_YUVJ444P +# define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P +# define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P +# define AV_PIX_FMT_YUV440P PIX_FMT_YUV440P +# define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P +#endif + +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) +# define av_frame_alloc avcodec_alloc_frame +# if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,59,100) +# define av_frame_free av_freep +# else +# define av_frame_free avcodec_free_frame +# endif +void av_frame_get_buffer(AVFrame *frame, int magic) { avpicture_alloc((AVPicture *)frame, frame->format, frame->width, frame->height); } +void av_frame_copy(AVFrame *dst, AVFrame *src) { memcpy(dst->data[0], src->data[0], sizeof(uint8_t)*avpicture_get_size(AV_PIX_FMT_RGB24, dst->width, dst->height)); } +#endif + +#define MAX_FILTER_SIZE 256 + +struct image { + AVFrame *frame; +}; + +image *image_init(const int width, const int height) { + image *i; + i = (image *) malloc(sizeof(image)); + + i->frame = (AVFrame *) av_frame_alloc(); + i->frame->width = width; + i->frame->height = height; + i->frame->format = AV_PIX_FMT_RGB24; // best choice? + av_frame_get_buffer(i->frame, 16); // magic number? + return i; +} + +int image_width(const image *i) { + return i->frame->width; +} + +int image_height(const image *i) { + return i->frame->height; +} + +void image_set(const image *i, const int x, const int y, const unsigned char r, const unsigned char g, const unsigned char b) { + *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+0) = r; + *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+1) = g; + *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+2) = b; +} + +unsigned char image_get_r(const image *i, const int x, const int y) { + return *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+0); +} + +unsigned char image_get_g(const image *i, const int x, const int y) { + return *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+1); +} + +unsigned char image_get_b(const image *i, const int x, const int y) { + return *(i->frame->data[0]+y*i->frame->linesize[0]+x*3+2); +} + +void image_to_bgra(unsigned char *target, const int width, const int height, const image *i, const int offset_x, const int offset_y) { + int x, y; + for (y = 0; y < image_height(i) && offset_y+y < height ; y++) { + for (x = 0; x < image_width(i) && offset_x+x < width; x++) { + *(target+width*4*(offset_y+y)+4*(offset_x+x)+0) = image_get_b(i, x, y); + *(target+width*4*(offset_y+y)+4*(offset_x+x)+1) = image_get_g(i, x, y); + *(target+width*4*(offset_y+y)+4*(offset_x+x)+2) = image_get_r(i, x, y); + *(target+width*4*(offset_y+y)+4*(offset_x+x)+3) = 255; + } + } +} + +image *image_from_bgra(const unsigned char *source, const int width, const int height) { + image *i = image_init(width, height); + int x, y; + for (y = 0; y < image_height(i); y++) { + for (x = 0; x < image_width(i); x++) { + image_set(i, x, y, *(source+width*4*y+4*x+2), *(source+width*4*y+4*x+1), *(source+width*4*y+4*x+0)); + } + } + return i; +} + +image* image_clone(const image *i) { + image *i2 = image_init(image_width(i), image_height(i)); + av_frame_copy(i2->frame, i->frame); + return i2; +} + +void image_copy_avframe(const image *i, AVFrame *frame) { + av_frame_copy(i->frame, frame); +} + +image* image_dumb_scale(const image *i, const int width, const int height) { + image *i2 = image_init(width, height); + + float x_factor = 1.0*image_width(i)/width; + float y_factor = 1.0*image_height(i)/height; + + int x, y; + for (x = 0; x < width; x++) { + int x_lower = x_factor*x + 0.5; + int x_upper = x_factor*(x+1) - 0.5; + + if (x_lower > x_upper) { + // this can happen when upscaling. pick nearest-neighbour entry + x_lower = x_upper = x_factor*(x+0.5); + } + + for (y = 0; y < height; y++) { + int y_lower = y_factor*y + 0.5; + int y_upper = y_factor*(y+1) - 0.5; + + if (y_lower > y_upper) { + // this can happen when upscaling. pick nearest-neighbour entry + y_lower = y_upper = y_factor*(y+0.5); + } + + int rsum = 0; + int gsum = 0; + int bsum = 0; + int xx, yy; + for (xx = x_lower; xx <= x_upper; xx++) { + for (yy = y_lower; yy <= y_upper; yy++) { + rsum += image_get_r(i, xx, yy); + gsum += image_get_g(i, xx, yy); + bsum += image_get_b(i, xx, yy); + } + } + int n = (x_upper-x_lower+1)*(y_upper-y_lower+1); + image_set(i2, x, y, rsum/n, gsum/n, bsum/n); + } + } + + return i2; +} + +image* image_scale(const image *i, int width, int height) { + int target_width = width; + int target_height = height; + + if (width == image_width(i) && height == image_height(i)) { + return image_clone(i); + } + + image *i2 = NULL; + image *tmp = (image *) i; + do { + width = target_width; + height = target_height; + +#if LIBSWSCALE_VERSION_MICRO < 100 || LIBSWSCALE_VERSION_INT < AV_VERSION_INT(2, 1, 103) + if (width < 8) { + // libav and old FFmpeg versions don't allow scaling to a width of less than 8 + if (image_width(tmp) > 8) { + // but we can use it to go down to 8 + width = 8; + } else { + // all hope ist lost + image *i3 = image_dumb_scale(tmp, width, height); + if (tmp != i) { + image_free(tmp); + } + return i3; + } + } + + if (height < 2) { + // This doesn't seem to work on libav... + if (image_height(tmp) > 2) { + height = 2; + } else { + image *i3 = image_dumb_scale(tmp, width, height); + if (tmp != i) { + image_free(tmp); + }
View file
nordlicht-0.4.5.tar.xz/src/image.h
Changed
(renamed from image.h)
View file
nordlicht-0.4.5.tar.xz/src/main.c
Added
@@ -0,0 +1,304 @@ +#include <sys/file.h> +#include <sys/mman.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> +#include <popt.h> +#include "nordlicht.h" +#include "version.h" + +#ifdef _WIN32 +// from http://stackoverflow.com/a/8514474/248734 +char* strsep(char** stringp, const char* delim) { + char* start = *stringp; + char* p; + + p = (start != NULL) ? strpbrk(start, delim) : NULL; + + if (p == NULL) { + *stringp = NULL; + } else { + *p = '\0'; + *stringp = p + 1; + } + + return start; +} +#endif + +typedef struct { + const char *name; + const char *description; + nordlicht_style style; +} style; + +const style style_table[] = { + {"horizontal", "compress frames to vertical lines and append them", NORDLICHT_STYLE_HORIZONTAL}, + {"vertical", "compress frames to horizontal lines and rotate them counterclockwise by 90 degrees", NORDLICHT_STYLE_VERTICAL}, + {"slitscan", "take single columns while constantly moving to the right (and wrapping back to the left)", NORDLICHT_STYLE_SLITSCAN}, + {"middlecolumn", "take the middlemost column of each frame", NORDLICHT_STYLE_MIDDLECOLUMN}, + {"thumbnails", "display small thumbnails at regular intervals", NORDLICHT_STYLE_THUMBNAILS}, + {"spectrogram", "spectrogram of the first audio track (not all sample formats are supported yet)", NORDLICHT_STYLE_SPECTROGRAM}, + {NULL, NULL, NORDLICHT_STYLE_LAST} +}; + +void print_error(const char *message, ...) { + fprintf(stderr, "nordlicht: "); + va_list arglist; + va_start(arglist, message); + vfprintf(stderr, message, arglist); + va_end(arglist); + fprintf(stderr, "\n"); +} + +const char *filename_ext(const char *path) { + const char *dot = strrchr(path, '.'); + if (!dot || dot == path) return ""; + return dot+1; +} + +void print_help(const poptContext popt, const int ret) { + poptPrintHelp(popt, ret == 0 ? stdout : stderr, 0); + + printf("\nStyles:\n"); + int i; + for (i = 0; style_table[i].name; i++) { + printf(" %-14s %s\n", style_table[i].name, style_table[i].description); + } + + printf("\n\ +Examples:\n\ + nordlicht video.mp4 generate video.mp4.nordlicht.png of default size\n\ + nordlicht video.mp4 -s vertical compress individual frames to columns\n\ + nordlicht video.mp4 -w 1000 -h 1000 -o barcode.png override size and name of the output file\n"); + + exit(ret); +} + +int main(const int argc, const char **argv) { + int width = -1; + int height = -1; + float start = 0.0; + float end = 1.0; + char *output_file = NULL; + char *styles_string = NULL; + nordlicht_strategy strategy; + int free_output_file = 0; + + int quiet = 0; + int help = 0; + int version = 0; + + const struct poptOption optionsTable[] = { + {"width", 'w', POPT_ARG_INT, &width, 0, "set the barcode's width; by default it's \"height*10\", or 1920 pixels, if both are undefined", NULL}, + {"height", 'h', POPT_ARG_INT, &height, 0, "set the barcode's height; by default it's \"width/10\"", NULL}, + {"output", 'o', POPT_ARG_STRING, &output_file, 0, "set output filename, the default is VIDEOFILE.png; when you specify an *.bgra file, you'll get a raw 32-bit BGRA file that is updated as the barcode is generated", "FILENAME"}, + {"style", 's', POPT_ARG_STRING, &styles_string, 0, "default is 'horizontal', see \"Styles\" section below. You can specify more than one style, separated by '+', to get multiple tracks", "STYLE"}, + {"start", '\0', POPT_ARG_FLOAT, &start, 0, "specify where to start the barcode (ratio between 0 and 1)", NULL}, + {"end", '\0', POPT_ARG_FLOAT, &end, 0, "specify where to end the barcode (ratio between 0 and 1)", NULL}, + {"quiet", 'q', 0, &quiet, 0, "don't show progress indicator", NULL}, + {"help", '\0', 0, &help, 0, "display this help and exit", NULL}, + {"version", '\0', 0, &version, 0, "output version information and exit", NULL}, + POPT_TABLEEND + }; + + const poptContext popt = poptGetContext(NULL, argc, argv, optionsTable, 0); + poptSetOtherOptionHelp(popt, "[OPTION]... VIDEOFILE\n\nOptions:"); + + if (argc == 1) { + print_help(popt, 1); + } + + int option; + + // The next line leaks 2 bytes, blame popt! + while ((option = poptGetNextOpt(popt)) >= 0) { } + + if (option < -1) { + fprintf(stderr, "nordlicht: %s: %s\n", poptBadOption(popt, POPT_BADOPTION_NOALIAS), poptStrerror(option)); + return 1; + } + + if (version) { + printf("nordlicht %s\n\nWritten by Sebastian Morr and contributors.\n", NORDLICHT_VERSION); + return 0; + } + + if (help) { + print_help(popt, 0); + } + + const char *filename = (char*)poptGetArg(popt); + + if (filename == NULL) { + print_error("Please specify an input file."); + exit(1); + } + + if (poptGetArg(popt) != NULL) { + print_error("Please specify only one input file."); + exit(1); + } + + if (output_file == NULL) { + size_t len = snprintf(NULL, 0, "%s.nordlicht.png", filename) + 1; + output_file = (char *) malloc(len); + snprintf(output_file, len, "%s.nordlicht.png", filename); + free_output_file = 1; + } + + if (width == -1 && height != -1) { + width = height*10; + } + if (height == -1 && width != -1) { + height = width/10; + if (height < 1) { + height = 1; + } + } + if (height == -1 && width == -1) { + width = 1920; + height = 192; + } + + if (styles_string == NULL) { + styles_string = "horizontal"; + } + + // count the occurrences of "+" in the styles_string + const char *s = styles_string; + int num_tracks; + for (num_tracks=0; s[num_tracks]; s[num_tracks]=='+' ? num_tracks++ : *s++); + num_tracks++; + + nordlicht_style *styles; + styles = (nordlicht_style *) malloc(num_tracks * sizeof(nordlicht_style)); + + const char *style_string; + num_tracks = 0; + while ((style_string = strsep(&styles_string, "+"))) { + int i; + for (i = 0; style_table[i].name; i++) { + if (strcmp(style_string, style_table[i].name) == 0) { + styles[num_tracks] = style_table[i].style; + break; + } + } + + if (!style_table[i].name) { + print_error("Unknown style '%s'. Use '--help' to display available styles.", style_string); + exit(1); + } + num_tracks++; + } + + const char *ext = filename_ext(output_file); + if (strcmp(ext, "bgra") == 0) { + strategy = NORDLICHT_STRATEGY_LIVE; + } else if (strcmp(ext, "png") == 0) { + strategy = NORDLICHT_STRATEGY_FAST;
View file
nordlicht-0.4.5.tar.xz/src/nordlicht.c
Added
@@ -0,0 +1,385 @@ +#include "nordlicht.h" +#include <string.h> +#include "error.h" +#include "source.h" + +#ifdef _WIN32 +#define realpath(N,R) _fullpath((R),(N),_MAX_PATH) +#endif + +typedef struct { + nordlicht_style style; + int height; +} track; + +struct nordlicht { + int width, height; + char *filename; + track *tracks; + int num_tracks; + unsigned char *data; + + int owns_data; + int modifiable; + nordlicht_strategy strategy; + source *source; + + int current_pass; + int current_track; + int current_column; + int current_y_offset; + float progress; +}; + +NORDLICHT_API size_t nordlicht_buffer_size(const nordlicht *n) { + return n->width * n->height * 4; +} + +NORDLICHT_API nordlicht* nordlicht_init(const char *filename, const int width, const int height) { + if (width < 1 || height < 1) { + error("Dimensions must be positive (got %dx%d)", width, height); + return NULL; + } + if (width > 100000 || height > 100000) { + error("Both dimensions may be at most 100000 (got %dx%d)", width, height); + return NULL; + } + nordlicht *n; + n = (nordlicht *) malloc(sizeof(nordlicht)); + + n->width = width; + n->height = height; + + // prepend "file:" if filename contains a colon and is not a URL, + // otherwise ffmpeg will fail to open the file + if (filename && strstr(filename, ":") != 0 && strstr(filename, "://") == 0) { + size_t filename_len = strlen(filename); + n->filename = malloc(filename_len + 5 + 1); + strncpy(n->filename, "file:", 5); + strncpy(n->filename + 5, filename, filename_len); + n->filename[filename_len + 5] = '\0'; + } else { + n->filename = (char *) filename; + } + + n->data = (unsigned char *) calloc(nordlicht_buffer_size(n), 1); + if (n->data == 0) { + error("Not enough memory to allocate %d bytes", nordlicht_buffer_size(n)); + return NULL; + } + + n->owns_data = 1; + + n->num_tracks = 1; + n->tracks = (track *) malloc(sizeof(track)); + n->tracks[0].style = NORDLICHT_STYLE_HORIZONTAL; + n->tracks[0].height = n->height; + + n->strategy = NORDLICHT_STRATEGY_FAST; + n->modifiable = 1; + n->source = source_init(n->filename); + + n->current_pass = -1; + n->current_track = 0; + n->current_column = 0; + n->current_y_offset = 0; + n->progress = 0; + + if (n->source == NULL) { + error("Could not open video file '%s'", filename); + free(n); + return NULL; + } + + return n; +} + +NORDLICHT_API void nordlicht_free(nordlicht *n) { + if (n->owns_data) { + free(n->data); + } + free(n->tracks); + source_free(n->source); + free(n); +} + +NORDLICHT_API const char *nordlicht_error() { + return get_error(); +} + +NORDLICHT_API int nordlicht_set_start(nordlicht *n, const float start) { + if (! n->modifiable) { + return -1; + } + + if (start < 0) { + error("'start' has to be greater than or equal to 0."); + return -1; + } + + if (start >= source_end(n->source)) { + error("'start' has to be less than 'end'."); + return -1; + } + + source_set_start(n->source, start); + return 0; +} + +NORDLICHT_API int nordlicht_set_end(nordlicht *n, const float end) { + if (! n->modifiable) { + return -1; + } + + if (end > 1) { + error("'end' has to less than or equal to 1."); + return -1; + } + + if (source_start(n->source) >= end) { + error("'start' has to be less than 'end'."); + return -1; + } + + source_set_end(n->source, end); + return 0; +} + +NORDLICHT_API int nordlicht_set_style(nordlicht *n, const nordlicht_style style) { + if (! n->modifiable) { + return -1; + } + + nordlicht_style styles[1] = {style}; + return nordlicht_set_styles(n, styles, 1); +} + +NORDLICHT_API int nordlicht_set_styles(nordlicht *n, const nordlicht_style *styles, const int num_tracks) { + if (! n->modifiable) { + return -1; + } + + n->num_tracks = num_tracks; + + if (n->num_tracks > n->height) { + error("Height of %d px is too low for %d styles", n->height, n->num_tracks); + return -1; + } + + free(n->tracks); + n->tracks = (track *) malloc(n->num_tracks*sizeof(track)); + + int height_of_each_track = n->height/n->num_tracks; + int i; + for (i=0; i<num_tracks; i++) { + nordlicht_style s = styles[i]; + if (s > NORDLICHT_STYLE_LAST-1) { + return -1; + } + + n->tracks[i].style = s; + n->tracks[i].height = height_of_each_track; + } + n->tracks[0].height = n->height - (n->num_tracks-1)*height_of_each_track; + + return 0; +} + +NORDLICHT_API int nordlicht_set_strategy(nordlicht *n, const nordlicht_strategy s) { + if (! n->modifiable) { + return -1; + } + if (s > NORDLICHT_STRATEGY_LIVE) { + return -1; + } + n->strategy = s; + return 0; +} + +NORDLICHT_API int nordlicht_generate_step(nordlicht *n) {
View file
nordlicht-0.4.5.tar.xz/src/nordlicht.h
Added
@@ -0,0 +1,116 @@ +#ifndef INCLUDE_nordlicht_h__ +#define INCLUDE_nordlicht_h__ +#include <stdlib.h> // for size_t + +#ifndef NORDLICHT_API +# ifdef _WIN32 +# if defined(NORDLICHT_BUILD_SHARED) /* build dll */ +# define NORDLICHT_API __declspec(dllexport) +# elif !defined(NORDLICHT_BUILD_STATIC) /* use dll */ +# define NORDLICHT_API __declspec(dllimport) +# else /* static library */ +# define NORDLICHT_API +# endif +# else +# if __GNUC__ >= 4 +# define NORDLICHT_API __attribute__((visibility("default"))) +# else +# define NORDLICHT_API +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct nordlicht nordlicht; + +typedef enum nordlicht_style { + NORDLICHT_STYLE_THUMBNAILS, // a row of thumbnails + NORDLICHT_STYLE_HORIZONTAL, // compress frames to columns + NORDLICHT_STYLE_VERTICAL, // compress frames to rows and rotate them counterclockwise + NORDLICHT_STYLE_SLITSCAN, // take single columns, while moving to the right (and wrapping to the left) + NORDLICHT_STYLE_MIDDLECOLUMN, // take the frames' middlemost column + NORDLICHT_STYLE_SPECTROGRAM, // spectrogram of the first audio track (not all sample formats are supported yet) + NORDLICHT_STYLE_LAST // just a marker so that we can count the number of available styles +} nordlicht_style; + +typedef enum nordlicht_strategy { + NORDLICHT_STRATEGY_FAST, // generate barcode in a single pass as fast as possible + NORDLICHT_STRATEGY_LIVE, // generate a fast approximation first, good for live display +} nordlicht_strategy; + +// Returns a description of the last error, or NULL if there was no error. +NORDLICHT_API const char *nordlicht_error(); + +// Allocate a new nordlicht of specified width and height, for a given video +// file. Use `nordlicht_free` to free the nordlicht again. +// Returns NULL on errors. +NORDLICHT_API nordlicht* nordlicht_init(const char *filename, const int width, const int height); + +// Free a nordlicht. +NORDLICHT_API void nordlicht_free(nordlicht *n); + +// Specify where to start the nordlicht in the file, as a ratio between 0 and 1. +NORDLICHT_API int nordlicht_set_start(nordlicht *n, const float start); + +// Specify where to end the nordlicht in the file, as a ratio between 0 and 1. +NORDLICHT_API int nordlicht_set_end(nordlicht *n, const float end); + +// Set the output style of the nordlicht, see above. Default is NORDLICHT_STYLE_HORIZONTAL. +// To set multiple styles at once, use `nordlicht_set_styles`. +// Returns 0 on success. +NORDLICHT_API int nordlicht_set_style(nordlicht *n, const nordlicht_style style); + +// Set multiple output styles, which will be displayed on top of each other. +// Expects a pointer to an array of nordlicht_style-s of length `num_styles`. +// Returns 0 on success. +NORDLICHT_API int nordlicht_set_styles(nordlicht *n, const nordlicht_style *styles, const int num_styles); + +// Set the generation strategy of the nordlicht, see above. Default is NORDLICHT_STRATEGY_FAST. +// Returns 0 on success. +NORDLICHT_API int nordlicht_set_strategy(nordlicht *n, const nordlicht_strategy strategy); + +// Return a pointer to the nordlicht's internal buffer. You can use it to draw +// the barcode while it is generated. The pixel format is 32-bit BGRA. +NORDLICHT_API const unsigned char* nordlicht_buffer(const nordlicht *n); + +// Replace the internal nordlicht's internal buffer. The data pointer is owned +// by the caller and must be freed after `nordlicht_free`. You can use this to +// render the nordlicht into caller-owned data structures, like mmap-ed files. +// The pixel format is 32-bit BGRA. +// Returns 0 on success. +NORDLICHT_API int nordlicht_set_buffer(nordlicht *n, unsigned char *data); + +// Returns the size of this nordlicht's buffer in bytes. +NORDLICHT_API size_t nordlicht_buffer_size(const nordlicht *n); + +// Generate the nordlicht in one pass. Use this function from a thread if you don't +// want to block execution. Calling this will freeze the nordlicht: "set" +// functions will fail. +// Returns 0 on success. +NORDLICHT_API int nordlicht_generate(nordlicht *n); + +// Do one step of generation, which will be as small as possible. Use this +// if you don't want to start a seperate thread, but be aware that this +// function might still take too long for real-time applications. Calling this +// will freeze the nordlicht: "set" functions will fail. +// Returns 0 on success. +NORDLICHT_API int nordlicht_generate_step(nordlicht *n); + +// Returns 1 if the nordlicht has been completely generated, and 0 otherwise. +NORDLICHT_API int nordlicht_done(const nordlicht *n); + +// Returns a value between 0 and 1 indicating how much of the nordlicht has been +// generated. +NORDLICHT_API float nordlicht_progress(const nordlicht *n); + +// Write the nordlicht to a PNG file. Returns 0 on success. +NORDLICHT_API int nordlicht_write(const nordlicht *n, const char *filename); + +#ifdef __cplusplus +} +#endif + +#endif
View file
nordlicht-0.4.5.tar.xz/src/source.c
Added
@@ -0,0 +1,547 @@ +#include "source.h" +#include "error.h" +#include <libavcodec/avcodec.h> +#include <libavcodec/avfft.h> +#include <libavformat/avformat.h> +#include <libavutil/avutil.h> +#include <libswscale/swscale.h> + +// Changes for ffmpeg 3.0 +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57,24,0) +# include <libavutil/imgutils.h> +# define av_free_packet av_packet_unref +# define avpicture_get_size(fmt,w,h) av_image_get_buffer_size(fmt,w,h,1) +#endif + +// PIX_FMT was renamed to AV_PIX_FMT on this version +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51,74,100) +# define AVPixelFormat PixelFormat +# define AV_PIX_FMT_RGB24 PIX_FMT_RGB24 +# define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P +# define AV_PIX_FMT_YUVJ422P PIX_FMT_YUVJ422P +# define AV_PIX_FMT_YUVJ440P PIX_FMT_YUVJ440P +# define AV_PIX_FMT_YUVJ444P PIX_FMT_YUVJ444P +# define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P +# define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P +# define AV_PIX_FMT_YUV440P PIX_FMT_YUV440P +# define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P +#endif + +#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 8, 0) +# define av_frame_alloc avcodec_alloc_frame +# if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54,59,100) +# define av_frame_free av_freep +# else +# define av_frame_free avcodec_free_frame +# endif +#endif + +#define HEURISTIC_NUMBER_OF_FRAMES 1800 // how many frames will the heuristic look at? +#define HEURISTIC_KEYFRAME_FACTOR 1 // lower bound for the actual/required keyframe ratio + +#define SAMPLES_PER_FRAME 1024 + +typedef struct { + int stream; + AVCodecContext *codec; + image *last_frame; + + double time_base; + double fps; + AVFrame *frame; + long current_frame; +} stream; + +struct source { + int exact; + float start, end; + + AVFormatContext *format; + stream *video; + stream *audio; + + uint8_t *buffer; + AVFrame *scaleframe; + struct SwsContext *sws_context; + AVPacket packet; + + // audio specific + RDFTContext *rdft; + + int *keyframes; + int number_of_keyframes; + int has_index; + int current_frame; +}; + +long packet_pts(stream *st, const AVPacket *packet) { + long pts = packet->pts != 0 ? packet->pts : packet->dts; + double sec = st->time_base*pts; + return (int64_t)(st->fps*sec + 0.5); +} + +int grab_next_frame(source *s, stream *st) { + int valid = 0; + int got_frame = 0; + + long pts; + + while (!valid) { + if (av_read_frame(s->format, &s->packet) >= 0) { + if (s->packet.stream_index == st->stream) { + switch (st->codec->codec_type) { + case AVMEDIA_TYPE_VIDEO: + avcodec_decode_video2(st->codec, st->frame, &got_frame, &s->packet); + break; + case AVMEDIA_TYPE_AUDIO: + avcodec_decode_audio4(st->codec, st->frame, &got_frame, &s->packet); + break; + default: + error("Stream has unknown media type."); +#ifdef DEBUG + printf("Unknown media type?\n"); +#endif + return 1; + } + + if (got_frame) { + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (st->frame->data[0] == 0) { +#ifdef DEBUG + printf("grab_next_frame: st->frame->data[0] == 0\n"); +#endif + return 1; + } + } + pts = packet_pts(st, &s->packet); + valid = 1; + } + } + av_free_packet(&s->packet); + } else { + av_free_packet(&s->packet); + st->current_frame = -1; +#ifdef DEBUG + printf("grab_next_frame: av_read_frame() == 0\n"); +#endif + return 1; + } + } + + av_free_packet(&s->packet); + st->current_frame = pts; +#ifdef DEBUG + printf("grab_next_frame() grabbed frame %d\n", pts); +#endif + return 0; +} + +int seek_keyframe(source *s, stream *st, const long frame) { +#ifdef DEBUG + printf("seek_keyframe(%ld)\n", frame); +#endif + av_seek_frame(s->format, st->stream, frame/st->fps/st->time_base, AVSEEK_FLAG_BACKWARD); + avcodec_flush_buffers(st->codec); + return grab_next_frame(s, st) != 0; +} + +int total_number_of_frames(const source *s, stream *st) { + double duration_sec = 1.0*s->format->duration/AV_TIME_BASE; + return st->fps*duration_sec; +} + +// Returns 0 if done +int source_build_keyframe_index_step(source *s, const int width) { + if (s->keyframes == NULL) { + if (! s->video) { + return 0; + } + s->keyframes = (int *) malloc(sizeof(long)*60*60*3); // TODO: dynamic datastructure! + s->keyframes[0] = 0; + s->number_of_keyframes = 1; + + s->current_frame = 0; + + s->has_index = 0; + s->exact = 1; + } + + if (av_read_frame(s->format, &s->packet) >= 0) { + if (s->packet.stream_index == s->video->stream) { + if (!!(s->packet.flags & AV_PKT_FLAG_KEY)) { + s->number_of_keyframes++; + + long pts = packet_pts(s->video, &s->packet); + if (pts < 1 && s->number_of_keyframes > 0) { + pts = s->current_frame; + } + +#ifdef DEBUG + printf("Found a keyframe: %ld\n", pts); +#endif + s->keyframes[s->number_of_keyframes] = pts; + } + if (s->current_frame == HEURISTIC_NUMBER_OF_FRAMES) { + const float density = 1.0*s->number_of_keyframes/HEURISTIC_NUMBER_OF_FRAMES; + const float required_density = 1.0*HEURISTIC_KEYFRAME_FACTOR/COLUMN_PRECISION*width/total_number_of_frames(s, s->video)/(s->end-s->start); + if (density > required_density) { + // The keyframe density in the first `HEURISTIC_NUMBER_OF_FRAMES` + // frames is HEURISTIC_KEYFRAME_FACTOR times higher than + // the density we need overall. This means that we can abort build + // the keyframe index and just seek inexactly to get good results. + av_free_packet(&s->packet); +#ifdef DEBUG + printf("Keyframe indexing not necessary. Aborting.\n"); +#endif + return 0; + } + } + s->current_frame++;
View file
nordlicht-0.4.5.tar.xz/src/source.h
Added
@@ -0,0 +1,37 @@ +#ifndef INCLUDE_source_h__ +#define INCLUDE_source_h__ + +#include "nordlicht.h" +#include "image.h" + +#define COLUMN_PRECISION 0.95 // choose a frame from this percentage at the middle of each column + +typedef struct source source; + +source* source_init(const char *filename); + +int source_has_video(source *s); + +int source_has_audio(source *s); + +image* source_get_video_frame(source *s, const double min_percent, const double max_percent); + +image* source_get_audio_frame(source *s, const double min_percent, const double max_percent); + +int source_build_keyframe_index_step(source *s, const int width); + +int source_has_index(const source *s); + +void source_set_exact(source *s, const int exact); + +float source_start(const source *s); + +void source_set_start(source *s, const float start); + +float source_end(const source *s); + +void source_set_end(source *s, const float end); + +void source_free(source *s); + +#endif
View file
nordlicht-0.4.5.tar.xz/src/testsuite.c
Added
@@ -0,0 +1,242 @@ +#include "cheat.h" +#include "nordlicht.h" + +#ifdef _WIN32 +#include <io.h> +#define F_OK 0 +#define access _access +#endif + +#define cheat_null(x) cheat_assert(NULL == (x)) +#define cheat_not_null(x) cheat_assert(NULL != (x)) +#define cheat_fail(x) cheat_assert(0 != (x)) +#define cheat_ok(x) cheat_assert(0 == (x)) + +CHEAT_DECLARE( + nordlicht *n; + + int tool(char *args) { + char c[200]; + snprintf(c, 200, "./nordlicht %s >/dev/null 2>/dev/null", args); + return system(c); + } +) + +CHEAT_SET_UP( + n = NULL; +) + +CHEAT_TEAR_DOWN( + if (n != NULL) { + nordlicht_free(n); + } +) + +CHEAT_TEST(testfile_exists, + cheat_assert(-1 != access("video.mp4", F_OK)); +) + +CHEAT_TEST(invalid_input_file, + cheat_null(nordlicht_init(NULL, 100, 100)); + cheat_null(nordlicht_init("", 100, 100)); + cheat_null(nordlicht_init("\0", 100, 100)); + cheat_null(nordlicht_init(".", 100, 100)); + cheat_null(nordlicht_init("..", 100, 100)); + cheat_null(nordlicht_init("/", 100, 100)); + cheat_null(nordlicht_init("\\", 100, 100)); + cheat_null(nordlicht_init("nonexistent_file.123", 100, 100)); + cheat_null(nordlicht_init("video.mp4.", 100, 100)); +) + +CHEAT_TEST(invalid_size, + cheat_null(nordlicht_init("video.mp4", 0, 100)); + cheat_null(nordlicht_init("video.mp4", 100, 0)); + cheat_null(nordlicht_init("video.mp4", 0, 0)); + cheat_null(nordlicht_init("video.mp4", -1, 1)); + cheat_null(nordlicht_init("video.mp4", 1, -1)); + cheat_null(nordlicht_init("video.mp4", -100, 100)); + cheat_null(nordlicht_init("video.mp4", 100, -100)); + cheat_null(nordlicht_init("video.mp4", INT_MIN, INT_MIN)); + cheat_null(nordlicht_init("video.mp4", 100001, 100001)); + cheat_null(nordlicht_init("video.mp4", 100001, 1)); + cheat_null(nordlicht_init("video.mp4", 1, 100001)); +) + + +CHEAT_TEST(valid_size, + cheat_not_null(nordlicht_init("video.mp4", 1, 1)); + cheat_not_null(nordlicht_init("video.mp4", 100, 100)); + cheat_not_null(nordlicht_init("video.mp4", 100000, 100000)); + cheat_not_null(nordlicht_init("video.mp4", 100000, 1)); + cheat_not_null(nordlicht_init("video.mp4", 1, 100000)); +) + +CHEAT_TEST(invalid_output, + n = nordlicht_init("video.mp4", 100, 100); + cheat_not_null(n); + cheat_fail(nordlicht_write(n, NULL)); + cheat_fail(nordlicht_write(n, "")); + cheat_fail(nordlicht_write(n, "\0")); + cheat_fail(nordlicht_write(n, ".")); + cheat_fail(nordlicht_write(n, "..")); + cheat_fail(nordlicht_write(n, "/")); + cheat_fail(nordlicht_write(n, "video.mp4")); +) + +CHEAT_TEST(style, + n = nordlicht_init("video.mp4", 100, 100); + cheat_not_null(n); + cheat_ok(nordlicht_set_style(n, NORDLICHT_STYLE_HORIZONTAL)); + cheat_ok(nordlicht_set_style(n, NORDLICHT_STYLE_VERTICAL)); + cheat_ok(nordlicht_set_style(n, NORDLICHT_STYLE_LAST-1)); + cheat_fail(nordlicht_set_style(n, -1)); + cheat_fail(nordlicht_set_style(n, INT_MAX)); + cheat_fail(nordlicht_set_style(n, INT_MIN)); +) + +CHEAT_TEST(styles, + n = nordlicht_init("video.mp4", 100, 2); + cheat_not_null(n); + nordlicht_style styles[3]; + styles[0] = NORDLICHT_STYLE_HORIZONTAL; + styles[1] = NORDLICHT_STYLE_VERTICAL; + cheat_ok(nordlicht_set_styles(n, styles, 2)); + styles[0] = NORDLICHT_STYLE_LAST-1; + cheat_ok(nordlicht_set_styles(n, styles, 2)); + styles[0] = INT_MAX; + cheat_fail(nordlicht_set_styles(n, styles, 2)); + styles[0] = INT_MIN; + cheat_fail(nordlicht_set_styles(n, styles, 2)); + styles[2] = NORDLICHT_STYLE_HORIZONTAL; + cheat_fail(nordlicht_set_styles(n, styles, 3)); +) + +CHEAT_TEST(strategy, + n = nordlicht_init("video.mp4", 100, 100); + cheat_not_null(n); + cheat_ok(nordlicht_set_strategy(n, NORDLICHT_STRATEGY_FAST)); + cheat_ok(nordlicht_set_strategy(n, NORDLICHT_STRATEGY_LIVE)); + cheat_fail(nordlicht_set_strategy(n, 2)); + cheat_fail(nordlicht_set_strategy(n, -1)); + cheat_fail(nordlicht_set_strategy(n, INT_MAX)); + cheat_fail(nordlicht_set_strategy(n, INT_MIN)); +) + +CHEAT_TEST(buffer, + const unsigned char *buffer = NULL; + n = nordlicht_init("video.mp4", 2, 100); + cheat_not_null(n); + buffer = nordlicht_buffer(n); + cheat_not_null(buffer); + cheat_assert(2*100*4 == nordlicht_buffer_size(n)); + unsigned char *buffer2 = NULL; + cheat_fail(nordlicht_set_buffer(n, buffer2)); + buffer2 = malloc(nordlicht_buffer_size(n)); + cheat_ok(nordlicht_set_buffer(n, buffer2)); + cheat_ok(nordlicht_set_buffer(n, buffer2)); + cheat_ok(nordlicht_set_buffer(n, buffer2)); + buffer = nordlicht_buffer(n); + cheat_assert(buffer == buffer2); + free(buffer2); +) + +CHEAT_TEST(generate_step, + n = nordlicht_init("video.mp4", 1, 100); + cheat_assert(0 == nordlicht_progress(n)); + cheat_assert(!nordlicht_done(n)); + cheat_ok(nordlicht_set_start(n, 0.5)); + cheat_assert(0 == nordlicht_generate_step(n)); + cheat_assert(!nordlicht_done(n)); + cheat_fail(nordlicht_set_start(n, 0.5)); + cheat_assert(0 == nordlicht_generate_step(n)); + cheat_assert(0 == nordlicht_generate_step(n)); + cheat_ok(nordlicht_generate(n)); + cheat_assert(nordlicht_done(n)); + cheat_assert(0 == nordlicht_generate_step(n)); + cheat_assert(nordlicht_done(n)); +) + +CHEAT_TEST(complete_run, + unsigned char *buffer2 = NULL; + n = nordlicht_init("video.mp4", 1, 100); + cheat_not_null(n); + cheat_ok(nordlicht_progress(n)); + cheat_ok(nordlicht_generate(n)); + cheat_assert(1 == nordlicht_progress(n)); + buffer2 = malloc(nordlicht_buffer_size(n)); + cheat_fail(nordlicht_set_buffer(n, buffer2)); + free(buffer2); +) + +CHEAT_TEST(tool_argument_parsing, + cheat_ok(tool("--help")); + cheat_ok(tool("--version")); + cheat_fail(tool("")); + cheat_fail(tool("--fubar")); + cheat_fail(tool("-1")); + cheat_fail(tool("one.mp4 two.mp4")); + cheat_fail(tool("does_not_exist.mp4")); +) + +CHEAT_TEST(tool_size, + cheat_ok(tool("video.mp4 -w 1 -h 1")); + cheat_ok(tool("video.mp4 -w 1 -h 100000")); + cheat_fail(tool("video.mp4 -w 1 -h 100001")); + cheat_fail(tool("video.mp4 -w huuuge")); + cheat_fail(tool("video.mp4 -w 0")); + cheat_fail(tool("video.mp4 -h 0")); + cheat_fail(tool("video.mp4 -w ''")); + cheat_fail(tool("video.mp4 -h ''")); + cheat_fail(tool("video.mp4 -w -100")); + cheat_fail(tool("video.mp4 -h -100")); + cheat_fail(tool("video.mp4 -w 1.1")); + cheat_fail(tool("video.mp4 -h 1.1")); + cheat_fail(tool("video.mp4 -w 1,1")); + cheat_fail(tool("video.mp4 -h 1,1")); +) + +CHEAT_TEST(tool_output, + cheat_ok(tool("video.mp4 -w 1"));
View file
nordlicht-0.4.5.tar.xz/src/version.h.in
Changed
(renamed from version.h.in)
View file
nordlicht-0.4.4.tar.gz/utils/mpv-nordlicht.lua -> nordlicht-0.4.5.tar.xz/utils/mpv-nordlicht.lua
Changed
@@ -25,6 +25,10 @@ function shutdown() off() kill() + + if buffer and buffer:len() > 0 then + os.remove(buffer) + end end function kill() @@ -41,7 +45,13 @@ video = mp.get_property("path") nordlicht = video..".nordlicht.png" - buffer = "/tmp/nordlicht.bgra" + + if buffer and buffer:len() > 0 then + os.remove(buffer) + end + local tmpbuffer = os.tmpname() + buffer = tmpbuffer .. ".nordlicht.mpv.bgra" + os.rename(tmpbuffer, buffer) local f = io.open(nordlicht, "r") if f ~= nil then @@ -49,6 +59,7 @@ io.close(f) local cmd = {"convert", nordlicht, "-depth", "8", "-resize", width.."x"..height.."!", buffer} utils.subprocess({args=cmd}) + utils.subprocess({args={"chmod", "600", buffer}}) if was_on then on() @@ -114,7 +125,14 @@ function regenerate() local was_on = is_on off() - local cmd = "(nice nordlicht -s "..styles.." \""..video.."\" -o "..buffer.." -w "..width.." -h "..height.." && convert -depth 8 -size "..width.."x"..height.." "..buffer.." \""..nordlicht.."\") &" + + local safe_buffer = buffer:gsub('"', '\\"') + local safe_video = video:gsub('"', '\\"') + local safe_nordlicht = nordlicht:gsub('"', '\\"') + local cmd = ('(nice nordlicht -s %s "%s" -o "%s" -w %d -h %d' .. + ' && convert -depth 8 -size %dx%d "%s" "%s") &') + :format(styles, safe_video, safe_buffer, width, height, + width, height, safe_buffer, safe_nordlicht) os.execute(cmd) if was_on then on() @@ -122,11 +140,14 @@ end function jump(e) - local mouseX, mouseY = mp.get_mouse_pos() - local osdX, osdY = mp.get_osd_resolution() - mouseX = 100.0*mouseX/osdX + local mouse_x, mouse_y = mp.get_mouse_pos() + local osd_x, osd_y = mp.get_osd_resolution() + local screen_y = mp.get_property("osd-height") + local absolute_mouse_y = 1.0*mouse_y/osd_y*screen_y - mp.commandv("seek", mouseX, "absolute-percent", "exact") + if absolute_mouse_y <= mh+height and is_on then + mp.commandv("seek", 100.0*mouse_x/osd_x, "absolute-percent", "exact") + end end -- wait until the osd-width is > 0, then init
View file
nordlicht-0.4.5.tar.xz/utils/nordlicht.thumbnailer
Added
@@ -0,0 +1,4 @@ +[Thumbnailer Entry] +TryExec=nordlicht +Exec=nordlicht --quiet %i --output %o --width %s --height %s +MimeType=video/jpeg;video/mp4;video/mpeg;video/quicktime;video/x-ms-asf;video/x-ms-wm;video/x-ms-wmv;video/x-msvideo;video/x-flv;video/x-matroska;video/webm;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.