Skip to content

Commit

Permalink
tools/convert: support for storing PNM/Y4M
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinPulec committed Nov 9, 2023
1 parent ea9558c commit 96373a1
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 10 deletions.
41 changes: 34 additions & 7 deletions src/video_frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,27 @@
*
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#endif // HAVE_CONFIG_H
#include "debug.h"

#include <assert.h>
#include <errno.h>
#include <math.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __linux__
#include <sys/mman.h>
#endif

#include "config_unix.h"
#include "config_win32.h"
#include "debug.h"
#include "utils/pam.h"
#include "utils/y4m.h"
#include "video_codec.h"
#include "video_frame.h"

#define MOD_NAME "[video frame] "

struct video_frame * vf_alloc(int count)
{
struct video_frame *buf;
Expand Down Expand Up @@ -563,6 +569,27 @@ const char *save_video_frame(struct video_frame *frame, const char *name, bool r
return filename;
}

struct video_frame *
load_video_frame(const char *name, codec_t codec, int width, int height)
{
FILE *in = fopen(name, "rb");
if (!in) {
perror("fopen");
return NULL;
}
struct video_frame *out = vf_alloc_desc_data(
(struct video_desc){ width, height, codec, 1.0, PROGRESSIVE, 1 });
size_t bytes = fread(out->tiles[0].data, 1, out->tiles[0].data_len, in);
fclose(in);
if (bytes == out->tiles[0].data_len) {
return out;
}
MSG(ERROR, "Cannot read %u B from %s, got only %zu B!\n",
out->tiles[0].data_len, name, bytes);
vf_free(out);
return NULL;
}

void
vf_copy_metadata(struct video_frame *dest, const struct video_frame *src)
{
Expand Down
2 changes: 2 additions & 0 deletions src/video_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ bool parse_fps(const char *fps, struct video_desc *desc);

bool save_video_frame_as_pnm(struct video_frame *frame, const char *name);
const char *save_video_frame(struct video_frame *frame, const char *name, bool raw);
struct video_frame *load_video_frame(const char *name, codec_t codec, int width,
int height);

void vf_copy_metadata(struct video_frame *dest, const struct video_frame *src);
void vf_store_metadata(const struct video_frame *f, void *);
Expand Down
4 changes: 3 additions & 1 deletion tools/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ astat_lib: astat.a
astat.a: astat.o src/compat/platform_pipe.o
ar rcs astat.a $^

convert: src/pixfmt_conv.o src/video_codec.o convert.o src/debug.o src/utils/color_out.o src/utils/misc.o
convert: src/pixfmt_conv.o src/video_codec.o convert.o src/debug.o \
src/utils/color_out.o src/utils/misc.o src/video_frame.o \
src/utils/pam.c src/utils/y4m.c
$(CXX) $^ -o convert

decklink_temperature: decklink_temperature.cpp ext-deps/DeckLink/Linux/DeckLinkAPIDispatch.o
Expand Down
35 changes: 33 additions & 2 deletions tools/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "../src/config_unix.h"
#include "../src/video_codec.h"
#include "../src/video_frame.h"

using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
Expand Down Expand Up @@ -59,6 +60,28 @@ static void print_conversions() {
}
}

static int
write_to_container(int width, int height, const char *in_f,
const char *out_fname)
{
const char *ext = strrchr(in_f, '.');
if (ext == nullptr) {
fprintf(stderr, "File with no extension!\n");
return 1;
}
codec_t c = get_codec_from_file_extension(ext + 1);
if (c == VIDEO_CODEC_NONE) {
fprintf(stderr, "wrong extension: %s!\n", ext);
return 1;
}
struct video_frame *f = load_video_frame(in_f, c, width, height);
if (f == nullptr) {
return 1;
}
save_video_frame(f, out_fname, false);
return 0;
}

int main(int argc, char *argv[]) {
if (argc == 2 && string("list-conversions") == argv[1]) {
print_conversions();
Expand All @@ -68,10 +91,15 @@ int main(int argc, char *argv[]) {
benchmark();
return 0;
}
if (argc < 7) {
if (argc != 5 && argc != 7) {
cout << "Tool to convert between UltraGrid raw pixel format with supported conversions.\n\n"
"Usage:\n"
"\t" << argv[0] << " <width> <height> <in_codec> <out_codec> <in_file> <out_file> | benchmark | help | list-conversions\n"
"\t" << argv[0] << " benchmark | help | list-conversions\n\n"
"\t" << argv[0] << " <width> <height> <in_codec> <out_codec> <in_file> <out_file>\n"
"\t\t" << "Eg.: " << argv[0] << " 1920 1080 UYVY RGB 00000001.yuv out.rgb\n\n"
"\t" << argv[0] << " <width> <height> <in_file> <oname_wo_ext>\n"
"\t\t- converts to output Y4M or PNM file (depending on in_file extension color space)\n"
"\t\t" << "Eg.: " << argv[0] << " 1920 1080 00000001.yuv out # creates out.y4m\n\n"
"\n"
"where\n"
"\t" << "benchmark - benchmark conversions\n"
Expand All @@ -81,6 +109,9 @@ int main(int argc, char *argv[]) {
}
int width = stoi(argv[1]);
int height = stoi(argv[2]);
if (argc == 5) {
return write_to_container(width, height, argv[3], argv[4]);
}
codec_t in_codec = get_codec_from_name(argv[3]);
codec_t out_codec = get_codec_from_name(argv[4]);
ifstream in(argv[5], ifstream::ate | ifstream::binary);
Expand Down

0 comments on commit 96373a1

Please sign in to comment.