UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
video_frame.c
Go to the documentation of this file.
1
14/*
15 * Copyright (c) 2005-2023 CESNET z.s.p.o.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, is permitted provided that the following conditions
19 * are met:
20 *
21 * 1. Redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer.
23 *
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 *
28 * 3. All advertising materials mentioning features or use of this software
29 * must display the following acknowledgement:
30 *
31 * This product includes software developed by CESNET z.s.p.o.
32 *
33 * 4. Neither the name of the CESNET nor the names of its contributors may be
34 * used to endorse or promote products derived from this software without
35 * specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
38 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
39 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
41 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
42 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
44 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
47 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
48 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 *
50 */
51
52#include <assert.h>
53#include <errno.h>
54#include <math.h>
55#include <stddef.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59#ifdef __linux__
60#include <sys/mman.h>
61#endif
62
63#include "config_unix.h"
64#include "config_win32.h"
65#include "debug.h"
66#include "pixfmt_conv.h"
67#include "utils/pam.h"
68#include "utils/y4m.h"
69#include "video_codec.h"
70#include "video_frame.h"
71
72#define MOD_NAME "[video frame] "
73
75{
76 struct video_frame *buf;
77 assert(count > 0);
78
79 buf = (struct video_frame *) calloc(1, offsetof (struct video_frame, tiles[count]));
80 assert(buf != NULL);
81
82 buf->tile_count = count;
83
84 return buf;
85}
86
88{
89 struct video_frame *buf;
90 assert(desc.tile_count > 0);
91
93 if(!buf) return NULL;
94
97 buf->fps = desc.fps;
98 // tile_count already filled
99 for(unsigned int i = 0u; i < desc.tile_count; ++i) {
100 buf->tiles[i].width = desc.width;
101 buf->tiles[i].height = desc.height;
104 } else {
106 }
107 }
108
109 return buf;
110}
111
112static void vf_aligned_data_deleter(struct video_frame *buf)
113{
114 for (unsigned int i = 0u; i < buf->tile_count; ++i) {
115 aligned_free(buf->tiles[i].data);
116 }
117}
118
127{
128 struct video_frame *buf;
129
130 buf = vf_alloc_desc(desc);
131
132 if (!buf) {
133 return NULL;
134 }
135 for(unsigned int i = 0; i < desc.tile_count; ++i) {
138 } else {
141 desc.height;
142 }
143 buf->tiles[i].data = (char *) aligned_malloc(buf->tiles[i].data_len + MAX_PADDING, 1U<<21U /* 2 MiB */);
144 assert(buf->tiles[i].data != NULL);
145#ifdef __linux__
146 madvise(buf->tiles[0].data, buf->tiles[0].data_len, MADV_HUGEPAGE);
147#endif
148 }
149
151 buf->callbacks.recycle = NULL;
152
153 return buf;
154}
155
156void vf_free(struct video_frame *buf)
157{
158 if(!buf)
159 return;
160
161 vf_recycle(buf);
162
163 if (buf->callbacks.data_deleter) {
164 buf->callbacks.data_deleter(buf);
165 }
166 free(buf);
167}
168
169void vf_recycle(struct video_frame *buf)
170{
171 if(!buf)
172 return;
173
174 if(buf->callbacks.recycle)
175 buf->callbacks.recycle(buf);
176}
177
179{
180 if(!buf)
181 return;
182
183 for(unsigned int i = 0u; i < buf->tile_count; ++i) {
184 free(buf->tiles[i].data);
185 }
186}
187
188struct tile * vf_get_tile(struct video_frame *buf, int pos)
189{
190 assert ((unsigned int) pos < buf->tile_count);
191
192 return &buf->tiles[pos];
193}
194
195bool video_desc_eq(struct video_desc a, struct video_desc b)
196{
197 return video_desc_eq_excl_param(a, b, 0);
198}
199
200bool video_desc_eq_excl_param(struct video_desc a, struct video_desc b, unsigned int excluded_params)
201{
202 return ((excluded_params & PARAM_WIDTH) || a.width == b.width) &&
203 ((excluded_params & PARAM_HEIGHT) || a.height == b.height) &&
204 ((excluded_params & PARAM_CODEC) || a.color_spec == b.color_spec) &&
205 ((excluded_params & PARAM_INTERLACING) || a.interlacing == b.interlacing) &&
206 ((excluded_params & PARAM_TILE_COUNT) || a.tile_count == b.tile_count) &&
207 ((excluded_params & PARAM_FPS) || fabs(a.fps - b.fps) < 0.01);// &&
208}
209
210struct video_desc
212{
213 struct video_desc desc;
214
215 assert(frame != NULL);
216
217 desc.width = frame->tiles[0].width;
220 desc.fps = frame->fps;
223
224 return desc;
225}
226
228{
229 switch (interlacing) {
230 case PROGRESSIVE:
231 return "progressive";
233 return "interlaced (upper field first)";
235 return "interlaced (lower field first)";
237 return "interlaced merged";
238 case SEGMENTED_FRAME:
239 return "progressive segmented";
240 }
241
242 return NULL;
243}
244
245static const char *interlacing_suffixes[] = {
246 [PROGRESSIVE] = "p",
247 [UPPER_FIELD_FIRST] = "tff",
248 [LOWER_FIELD_FIRST] = "bff",
249 [INTERLACED_MERGED] = "i",
250 [SEGMENTED_FRAME] = "psf",
251};
252
254{
257 return NULL;
258}
259
265{
266 for (size_t i = 0; i < sizeof interlacing_suffixes / sizeof interlacing_suffixes[0]; ++i) {
267 if (interlacing_suffixes[i] && strcmp(suffix, interlacing_suffixes[i]) == 0) {
268 return i;
269 }
270 }
271
272 return INTERLACING_MAX + 1;
273}
274
279void il_lower_to_merged(char *dst, char *src, int linesize, int height, void **stored_state)
280{
281 struct il_lower_to_merged_state {
282 size_t field_len;
283 char field[];
284 };
285 struct il_lower_to_merged_state *last_field = (struct il_lower_to_merged_state *) *stored_state;
286
287 char *tmp = malloc(linesize * height);
288 char *line1, *line2;
289
290 // upper field
291 line1 = tmp;
292 int upper_field_len = linesize * ((height + 1) / 2);
293 // first check if we have field from last frame
294 if (last_field == NULL) {
295 last_field = (struct il_lower_to_merged_state *)
296 malloc(sizeof(struct il_lower_to_merged_state) + upper_field_len);
297 last_field->field_len = upper_field_len;
298 *stored_state = last_field;
299 // if no, use current one
300 line2 = src + linesize * (height / 2);
301 } else {
302 // otherwise use field from last "frame"
303 line2 = last_field->field;
304 }
305 for (int y = 0; y < (height + 1) / 2; y++) {
306 memcpy(line1, line2, linesize);
307 line1 += linesize * 2;
308 line2 += linesize;
309 }
310 // store
311 assert ((int) last_field->field_len == upper_field_len);
312 memcpy(last_field->field, src + linesize * (height / 2), upper_field_len);
313
314 // lower field
315 line1 = tmp + linesize;
316 line2 = src;
317 for (int y = 0; y < height / 2; y++) {
318 memcpy(line1, line2, linesize);
319 line1 += linesize * 2;
320 line2 += linesize;
321 }
322 memcpy(dst, tmp, linesize * height);
323 free(tmp);
324}
325
326/* TODO: rewrite following 2 functions in more efficient way */
327void il_upper_to_merged(char *dst, char *src, int linesize, int height, void **state)
328{
329 UNUSED(state);
330 int y;
331 char *tmp = malloc(linesize * height);
332 char *line1, *line2;
333
334 line1 = tmp;
335 line2 = src;
336 for(y = 0; y < (height + 1) / 2; y ++) {
337 memcpy(line1, line2, linesize);
338 line1 += linesize * 2;
339 line2 += linesize;
340 }
341
342 line1 = tmp + linesize;
343 line2 = src + linesize * ((height + 1) / 2);
344 for(y = 0; y < height / 2; y ++) {
345 memcpy(line1, line2, linesize);
346 line1 += linesize * 2;
347 line2 += linesize;
348 }
349 memcpy(dst, tmp, linesize * height);
350 free(tmp);
351}
352
353void il_merged_to_upper(char *dst, char *src, int linesize, int height, void **state)
354{
355 UNUSED(state);
356 int y;
357 char *tmp = malloc(linesize * height);
358 char *line1, *line2;
359
360 line1 = tmp;
361 line2 = src;
362 for(y = 0; y < (height + 1) / 2; y ++) {
363 memcpy(line1, line2, linesize);
364 line1 += linesize;
365 line2 += linesize * 2;
366 }
367
368 line1 = tmp + linesize * ((height + 1) / 2);
369 line2 = src + linesize;
370 for(y = 0; y < height / 2; y ++) {
371 memcpy(line1, line2, linesize);
372 line1 += linesize;
373 line2 += linesize * 2;
374 }
375 memcpy(dst, tmp, linesize * height);
376 free(tmp);
377}
378
391double compute_fps(int fps, int fpsd, int fd, int fi)
392{
393 if (fpsd == 0) {
394 return -1;
395 }
396
397 double res = fps;
398 if (fd) {
399 res /= 1.001;
400 }
401 res /= fpsd;
402
403 if (fi) {
404 res = 1.0 / res;
405 }
406
407 return res;
408}
409
410struct video_frame *vf_get_copy(struct video_frame *original_frame) {
411 struct video_frame *frame_copy = vf_alloc_desc(video_desc_from_frame(original_frame));
412
413 for(int i = 0; i < (int) frame_copy->tile_count; ++i) {
414 frame_copy->tiles[i].data = (char *) malloc(frame_copy->tiles[i].data_len);
415 memcpy(frame_copy->tiles[i].data, original_frame->tiles[i].data,
416 frame_copy->tiles[i].data_len);
417 }
418
419 if(frame_copy->callbacks.copy){
420 frame_copy->callbacks.copy(frame_copy);
421 }
422
424
425 return frame_copy;
426}
427
431static unsigned char *get_16_bit_pnm_data(struct video_frame *frame) {
433 if (!dec) {
434 log_msg(LOG_LEVEL_WARNING, "Unable to find decoder from %s to RG48\n",
436 return NULL;
437 }
438 unsigned char *tmp = malloc(vc_get_datalen(frame->tiles[0].width, frame->tiles[0].height, RG48));
439 assert (tmp);
440 int src_linesize = vc_get_linesize(frame->tiles[0].width, frame->color_spec);
441 int dst_linesize = vc_get_linesize(frame->tiles[0].width, RG48);
443 for (unsigned i = 0; i < frame->tiles[0].height; ++i) {
444 uint16_t *dstline = (uint16_t *) (void *) (tmp + (size_t) i * dst_linesize);
445 dec((unsigned char *) dstline, (unsigned char *) frame->tiles[0].data + (size_t) i * src_linesize,
447 for (unsigned i = 0; i < frame->tiles[0].width * 3; ++i) {
448 uint16_t tmp = *dstline;
449 tmp >>= 16U - depth;
450 *dstline++ = htons(tmp);
451 }
452 }
453 return tmp;
454}
455
457{
458 unsigned char *data = NULL, *tmp_data = NULL;
459 struct tile *tile = &frame->tiles[0];
460 if (frame->color_spec == RGB) {
461 data = (unsigned char *) tile->data;
462 } else if (get_bits_per_component(frame->color_spec) <= 8 ||
465 if (!dec) {
466 log_msg(LOG_LEVEL_WARNING, "Unable to find decoder from %s to RGB\n",
468 return false;
469 }
470 int len = tile->width * tile->height * 3;
471 data = tmp_data = (unsigned char *) malloc(len);
472 dec (data, (const unsigned char *) tile->data, len, 0, 0, 0);
473 } else {
474 data = tmp_data = get_16_bit_pnm_data(frame);
475 if (!data) {
476 return false;
477 }
478 }
479
480 if (!data) {
481 return false;
482 }
483
485 free(tmp_data);
486
487 return true;
488}
489
490static bool save_video_frame_as_y4m(struct video_frame *frame, const char *name)
491{
492 struct tile *tile = &frame->tiles[0];
494 unsigned char *uyvy = (unsigned char *) tile->data;
495 unsigned char *tmp_data_uyvy = NULL;
496 if (frame->color_spec != UYVY) {
499 uyvy = tmp_data_uyvy = malloc(len);
500 dec (uyvy, (const unsigned char *) tile->data, len, 0, 0, 0);
501 }
502 unsigned char *i422 = malloc(tile->width * tile->height + 2 * ((tile->width + 1) / 2) * tile->height);
503 uyvy_to_i422(tile->width, tile->height, uyvy, i422);
504
505 struct y4m_metadata info = { .width = tile->width, .height = tile->height, .bitdepth = 8, .subsampling = Y4M_SUBS_422, .limited = true };
506 bool ret = y4m_write(name, &info, i422);
507 free(tmp_data_uyvy);
508 free(i422);
509 return ret;
511 unsigned char *y416 = (unsigned char *) tile->data;
512 unsigned char *tmp_data_y416 = NULL;
513 if (frame->color_spec != Y416) {
516 y416 = tmp_data_y416 = malloc(len);
517 dec (y416, (const unsigned char *) tile->data, len, 0, 0, 0);
518 }
519 unsigned char *i444 = malloc(tile->width * tile->height * 6);
521 y416_to_i444(tile->width, tile->height, y416, i444, depth);
522
523 struct y4m_metadata info = { .width = tile->width, .height = tile->height, .bitdepth = depth, .subsampling = Y4M_SUBS_444, .limited = true };
524 bool ret = y4m_write(name, &info, (unsigned char *) i444);
525 free(tmp_data_y416);
526 free(i444);
527 return ret;
528 }
529
530 log_msg(LOG_LEVEL_WARNING, "Unable to find decoder from %s to UYVY or Y416\n",
532 return false;
533}
534
538const char *save_video_frame(struct video_frame *frame, const char *name, bool raw) {
539 _Thread_local static char filename[FILENAME_MAX];
540 if (!raw && !is_codec_opaque(frame->color_spec)) {
544 snprintf(filename, sizeof filename, "%s.pnm", name);
545 bool ret = save_video_frame_as_pnm(frame, filename);
546 return ret ? filename : NULL;
547 } else if (!codec_is_a_rgb(frame->color_spec) &&
550 snprintf(filename, sizeof filename, "%s.y4m", name);
551 bool ret = save_video_frame_as_y4m(frame, filename);
552 return ret ? filename : NULL;
553 }
554 }
555 snprintf(filename, sizeof filename, "%s.%s", name, get_codec_file_extension(frame->color_spec));
556 errno = 0;
557 FILE *out = fopen(filename, "wb");
558 if (out == NULL) {
559 perror("save_video_frame fopen");
560 return NULL;
561 }
562 fwrite(frame->tiles[0].data, frame->tiles[0].data_len, 1, out);
563 if (ferror(out)) {
564 perror("save_video_frame fwrite");
565 fclose(out);
566 return NULL;
567 }
568 fclose(out);
569 return filename;
570}
571
572struct video_frame *
573load_video_frame(const char *name, codec_t codec, int width, int height)
574{
575 FILE *in = fopen(name, "rb");
576 if (!in) {
577 perror("fopen");
578 return NULL;
579 }
580 struct video_frame *out = vf_alloc_desc_data(
581 (struct video_desc){ width, height, codec, 1.0, PROGRESSIVE, 1 });
582 size_t bytes = fread(out->tiles[0].data, 1, out->tiles[0].data_len, in);
583 fclose(in);
584 if (bytes == out->tiles[0].data_len) {
585 return out;
586 }
587 MSG(ERROR, "Cannot read %u B from %s, got only %zu B!\n",
588 out->tiles[0].data_len, name, bytes);
589 vf_free(out);
590 return NULL;
591}
592
593void
594vf_copy_metadata(struct video_frame *dest, const struct video_frame *src)
595{
596 memcpy((char *) dest + offsetof(struct video_frame, VF_METADATA_START),
597 (const char *) src +
598 offsetof(struct video_frame, VF_METADATA_START),
600}
601
602void
603vf_store_metadata(const struct video_frame *f, void *s)
604{
605 memcpy(s,
606 (const char *) f +
607 offsetof(struct video_frame, VF_METADATA_START),
609}
610
611void vf_restore_metadata(struct video_frame *f, void *s)
612{
613 memcpy((char *) f + offsetof(struct video_frame, VF_METADATA_START), s, VF_METADATA_SIZE);
614}
615
616unsigned int vf_get_data_len(struct video_frame *f)
617{
618 unsigned int ret = 0;
619 for (unsigned int i = 0u; i < f->tile_count; ++i) {
620 ret += f->tiles[i].data_len;
621 }
622
623 return ret;
624}
625
626void buf_get_planes(int width, int height, codec_t color_spec, char *data, char **planes)
627{
628 char *tmp = data;
629 int sub[8];
631 for (int i = 0; i < 4; ++i) {
632 if (sub[i * 2] == 0) { // less than 4 planes
633 break;
634 }
635 planes[i] = tmp;
636 tmp += ((width + sub[i * 2] - 1) / sub[i * 2])
637 * ((height + sub[i * 2 + 1] - 1) / sub[i * 2 + 1]);
638 }
639}
640
641void buf_get_linesizes(int width, codec_t color_spec, int *linesize)
642{
643 int sub[8];
645 for (int i = 0; i < 4; ++i) {
646 if (sub[2 * i] == 0) {
647 break;
648 }
649 linesize[i] = (width + sub[2 * i] - 1) / sub[2 * i];
650 }
651}
652
653void vf_clear(struct video_frame *f)
654{
655 clear_video_buffer((unsigned char *)f->tiles[0].data,
658 f->tiles[0].height,
659 f->color_spec);
660}
661
662bool parse_fps(const char *fps, struct video_desc *desc)
663{
664 char *endptr = NULL;
665 desc->fps = strtod(fps, &endptr);
666 if (desc->fps <= 0.0) {
667 log_msg(LOG_LEVEL_ERROR, "FPS must be positive, got: %s!\n",
668 fps);
669 return false;
670 }
672 if (strlen(endptr) != 0) { // optional interlacing suffix
674 if (desc->interlacing != PROGRESSIVE &&
676 desc->interlacing != INTERLACED_MERGED) { // tff or bff
678 "Unsupported interlacing format: %s!\n",
679 endptr);
680 return false;
681 }
683 desc->fps /= 2;
684 }
685 }
686 return true;
687}
#define UNUSED(x)
void ** state
struct video_desc desc
struct video_frame * frame
int void size_t * len
int vc_get_linesize(unsigned int width, codec_t codec)
const char * get_codec_name(codec_t codec)
#define suffix(x, y)
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
int count
Definition hd-rum.c:44
static void * aligned_malloc(size_t size, size_t alignment)
#define aligned_free
bool pam_write(const char *filename, unsigned int width, unsigned int height, int depth, int maxval, const unsigned char *data, bool pnm)
Definition pam.c:204
decoder_t get_decoder_from_to(codec_t in, codec_t out)
#define DEFAULT_B_SHIFT
Definition pixfmt_conv.h:72
#define DEFAULT_R_SHIFT
Definition pixfmt_conv.h:70
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
#define DEFAULT_G_SHIFT
Definition pixfmt_conv.h:71
const char * name
Definition settings.cpp:193
Struct tile is an area of video_frame.
Definition types.h:279
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
unsigned int height
Definition types.h:281
unsigned int tile_count
Definition types.h:185
codec_t color_spec
Definition types.h:182
enum interlacing_t interlacing
Definition types.h:184
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
void(* data_deleter)(struct video_frame *)
Definition types.h:256
void(* recycle)(struct video_frame *)
Definition types.h:263
void(* copy)(struct video_frame *)
Definition types.h:271
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
enum interlacing_t interlacing
Definition types.h:307
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
double fps
Definition types.h:308
unsigned int tile_count
Definition types.h:344
struct video_frame_callbacks callbacks
Definition types.h:324
codec_t color_spec
Definition types.h:306
depth
Definition types.h:125
#define VF_METADATA_SIZE
Definition types.h:348
interlacing_t
Definition types.h:163
@ LOWER_FIELD_FIRST
First stored field is bottom, followed by top.
Definition types.h:166
@ UPPER_FIELD_FIRST
First stored field is top, followed by bottom.
Definition types.h:165
@ INTERLACING_MAX
Definition types.h:169
@ PROGRESSIVE
progressive frame
Definition types.h:164
@ SEGMENTED_FRAME
Segmented frame. Contains the same data as progressive frame.
Definition types.h:168
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
Definition types.h:167
#define VF_METADATA_START
Definition types.h:327
codec_t
Definition types.h:65
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ RG48
16-bit RGB little-endian (RlRhGl...)
Definition types.h:95
@ Y416
interleaved little-endian YCbCr 4444 16-bit - UYVA
Definition types.h:99
void codec_get_planes_subsampling(codec_t pix_fmt, int *sub)
void y416_to_i444(int width, int height, const unsigned char *in, unsigned char *out, int depth)
bool is_codec_opaque(codec_t codec)
void uyvy_to_i422(int width, int height, const unsigned char *in, unsigned char *out)
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).
bool codec_is_const_size(codec_t codec)
Returns TRUE if specified pixelformat has constant size regardles of resolution. If so the block_size...
int get_pf_block_bytes(codec_t codec)
returns codec_info_t::block_size_bytes
const char * get_codec_file_extension(codec_t codec)
bool clear_video_buffer(unsigned char *data, size_t linesize, size_t pitch, size_t height, codec_t color_spec)
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)
int get_bits_per_component(codec_t codec)
#define MAX_PADDING
Definition video_codec.h:63
struct video_frame * vf_alloc(int count)
Allocates blank video frame.
Definition video_frame.c:74
void vf_free(struct video_frame *buf)
Frees video_frame structure.
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
enum interlacing_t get_interlacing_from_suffix(const char *suffix)
void vf_clear(struct video_frame *f)
void il_merged_to_upper(char *dst, char *src, int linesize, int height, void **state)
Converts interlaced merged to upper-field-first.
void buf_get_linesizes(int width, codec_t color_spec, int *linesize)
void vf_data_deleter(struct video_frame *buf)
const char * save_video_frame(struct video_frame *frame, const char *name, bool raw)
bool video_desc_eq_excl_param(struct video_desc a, struct video_desc b, unsigned int excluded_params)
Compares two video descriptions.
const char * get_interlacing_suffix(enum interlacing_t interlacing)
Returns suffix describing interlacing Eg. p, i or psf.
static unsigned char * get_16_bit_pnm_data(struct video_frame *frame)
double compute_fps(int fps, int fpsd, int fd, int fi)
Computes FPS as a double from packet fields.
static const char * interlacing_suffixes[]
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
Definition video_frame.c:87
bool parse_fps(const char *fps, struct video_desc *desc)
unsigned int vf_get_data_len(struct video_frame *f)
void il_lower_to_merged(char *dst, char *src, int linesize, int height, void **stored_state)
void vf_recycle(struct video_frame *buf)
This function should be called before returning a frame back to a frame pool. Currently this is used ...
void vf_store_metadata(const struct video_frame *f, void *s)
bool save_video_frame_as_pnm(struct video_frame *frame, const char *name)
struct video_frame * vf_get_copy(struct video_frame *original_frame)
Makes deep copy of the video frame.
struct tile * vf_get_tile(struct video_frame *buf, int pos)
Returns pointer to n-th tile from video frame Equivalent to &video_frame::tiles[pos].
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
allocates struct video_frame including data pointers in RAM
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.
void vf_restore_metadata(struct video_frame *f, void *s)
const char * get_interlacing_description(enum interlacing_t interlacing)
Returns description of interlacing Eg. "progressive".
void il_upper_to_merged(char *dst, char *src, int linesize, int height, void **state)
Converts upper-field-first to interlaced merged.
void buf_get_planes(int width, int height, codec_t color_spec, char *data, char **planes)
void vf_copy_metadata(struct video_frame *dest, const struct video_frame *src)
static void vf_aligned_data_deleter(struct video_frame *buf)
static bool save_video_frame_as_y4m(struct video_frame *frame, const char *name)
struct video_frame * load_video_frame(const char *name, codec_t codec, int width, int height)
#define PARAM_TILE_COUNT
Definition video_frame.h:68
#define PARAM_CODEC
Definition video_frame.h:65
#define PARAM_FPS
Definition video_frame.h:67
#define PARAM_INTERLACING
Definition video_frame.h:66
#define PARAM_HEIGHT
Definition video_frame.h:64
#define PARAM_WIDTH
Definition video_frame.h:63
bool y4m_write(const char *filename, const struct y4m_metadata *info, const unsigned char *data)
Definition y4m.c:135
@ Y4M_SUBS_444
Definition y4m.h:53
@ Y4M_SUBS_422
Definition y4m.h:52