UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
deinterlace.c
Go to the documentation of this file.
1
7/*
8 * Copyright (c) 2014-2024 CESNET
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, is permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * 3. Neither the name of CESNET nor the names of its contributors may be
23 * used to endorse or promote products derived from this software without
24 * specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
28 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
30 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
37 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#include <assert.h> // for assert
41#include <stdbool.h> // for bool, true, false
42#include <stdlib.h>
43#include <string.h> // for strcmp, memcpy, strlen
44
45#include "capture_filter.h"
46#include "debug.h"
47#include "lib_common.h"
48#include "utils/color_out.h"
49#include "video.h"
50#include "video_frame.h"
51#include "vo_postprocess.h"
52struct module;
53
54#define MOD_NAME "[deinterlace_blend] "
55
57 struct video_frame *out;
58 _Bool force;
59};
60
61static void usage(_Bool for_postprocessor)
62{
63 color_printf(TBOLD("deinterlace_blend") " deinterlaces output video frames "
64 " by applying linear blend on interleaved odd and even "
65 " fileds.\n\nUsage:\n");
66 if (for_postprocessor) {
67 color_printf(TBOLD(TRED("\t-p deinterlace")) "[:options] | " TBOLD(TRED("-p deinterlace_blend")) "[:options]\n");
68 } else {
69 color_printf(TBOLD(TRED("\t--capture-filter deinterlace")) "[:options] -t <capture>\n");
70 }
71 color_printf("\noptions:\n"
72 "\t" TBOLD("force") " - apply deinterlacing even if input is progressive\n");
73}
74
75static void * deinterlace_blend_init(const char *config) {
76 if (strcmp(config, "help") == 0) {
77 usage(1);
78 return NULL;
79 }
80
81 struct state_deinterlace *s = calloc(1, sizeof(struct state_deinterlace));
82 assert(s != NULL);
83
84 if (strcmp(config, "force") == 0) {
85 s->force = 1;
86 } else if (strlen(config) > 0) {
87 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unknown option: %s\n", config);
88 free(s);
89 return NULL;
90 }
91
92 return s;
93}
94
95static void * deinterlace_init(const char *config) {
96 if (strcmp(config, "help") == 0) {
97 usage(1);
98 return NULL;
99 }
100
101 log_msg(LOG_LEVEL_INFO, MOD_NAME "\"-p deinterlace\" is equivalent to \"-p deinterlace_blend\", you can choose different implementations as well.\n");
102
103 return deinterlace_blend_init(config);
104}
105
106static int cf_deinterlace_init(struct module *parent, const char *cfg, void **state)
107{
108 UNUSED(parent);
109 if (strcmp(cfg, "help") == 0) {
110 usage(0);
111 return 1;
112 }
113 void *s = deinterlace_blend_init(cfg);
114 if (!s) {
115 return 1;
116 }
117 *state = s;
118 return 0;
119}
120
121static bool deinterlace_get_property(void *state, int property, void *val, size_t *len)
122{
123 UNUSED(state);
125 UNUSED(val);
126 UNUSED(len);
127
128 return false;
129}
130
131static bool
133{
134 struct state_deinterlace *s = (struct state_deinterlace *) state;
135
136 vf_free(s->out);
137 assert(desc.tile_count == 1);
139
140 return true;
141}
142
143static struct video_frame * deinterlace_getf(void *state)
144{
145 struct state_deinterlace *s = (struct state_deinterlace *) state;
146
147 return s->out;
148}
149
150static bool deinterlace_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch)
151{
152 assert (req_pitch == vc_get_linesize(in->tiles[0].width, in->color_spec));
156 assert (in->tiles[0].data_len <= vc_get_linesize(in->tiles[0].width, in->color_spec) * in->tiles[0].height);
157 assert (out->tiles[0].data_len <= vc_get_linesize(in->tiles[0].width, in->color_spec) * in->tiles[0].height);
158
159 struct state_deinterlace *s = state;
160 if (in->interlacing != INTERLACED_MERGED && !s->force) {
161 memcpy(out->tiles[0].data, in->tiles[0].data, in->tiles[0].data_len);
162 return true;
163 }
164
165 if (!vc_deinterlace_ex(in->color_spec, (unsigned char *) in->tiles[0].data, vc_get_linesize(in->tiles[0].width, in->color_spec),
166 (unsigned char *) out->tiles[0].data, vc_get_linesize(out->tiles[0].width, in->color_spec),
167 in->tiles[0].height)) {
168 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot deinterlace, unsupported pixel format '%s'!\n", get_codec_name(in->color_spec));
169 memcpy(out->tiles[0].data, in->tiles[0].data, in->tiles[0].data_len);
170 }
171
172 return true;
173}
174
175static struct video_frame *cf_deinterlace_filter(void *state, struct video_frame *f)
176{
177 UNUSED(state);
178
184 vf_free(out);
185 return NULL;
186 }
188 return out;
189}
190
191static void deinterlace_done(void *state)
192{
193 struct state_deinterlace *s = (struct state_deinterlace *) state;
194
195 vf_free(s->out);
196 free(s);
197}
198
199static void deinterlace_get_out_desc(void *state, struct video_desc *out, int *in_display_mode, int *out_frames)
200{
201 struct state_deinterlace *s = (struct state_deinterlace *) state;
202
204
205 UNUSED(in_display_mode);
206 //*in_display_mode = DISPLAY_PROPERTY_VIDEO_MERGED;
207 *out_frames = 1;
208}
209
219
229
235
239
#define UNUSED(x)
void ** state
int void * val
struct video_desc desc
int void size_t * len
int property
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.
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
const char * get_codec_name(codec_t codec)
#define CAPTURE_FILTER_ABI_VERSION
int color_printf(const char *format,...)
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
static void deinterlace_done(void *state)
static void * deinterlace_blend_init(const char *config)
Definition deinterlace.c:75
static void deinterlace_get_out_desc(void *state, struct video_desc *out, int *in_display_mode, int *out_frames)
static const struct capture_filter_info capture_filter_deinterlace_info
static struct video_frame * cf_deinterlace_filter(void *state, struct video_frame *f)
static bool deinterlace_get_property(void *state, int property, void *val, size_t *len)
static const struct vo_postprocess_info vo_pp_deinterlace_blend_info
#define MOD_NAME
Definition deinterlace.c:54
static struct video_frame * deinterlace_getf(void *state)
static const struct vo_postprocess_info vo_pp_deinterlace_info
static int cf_deinterlace_init(struct module *parent, const char *cfg, void **state)
static bool deinterlace_reconfigure(void *state, struct video_desc desc)
static bool deinterlace_postprocess(void *state, struct video_frame *in, struct video_frame *out, int req_pitch)
static void * deinterlace_init(const char *config)
Definition deinterlace.c:95
void usage()
Definition main.cpp:28
@ LIBRARY_CLASS_VIDEO_POSTPROCESS
Definition lib_common.h:83
@ LIBRARY_CLASS_CAPTURE_FILTER
Definition lib_common.h:75
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
const char * parent
Definition settings.cpp:198
struct video_frame * out
for postprocess only
Definition deinterlace.c:57
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
void(* dispose)(struct video_frame *)
Definition types.h:245
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
struct video_frame_callbacks callbacks
Definition types.h:324
codec_t color_spec
Definition types.h:306
@ PROGRESSIVE
progressive frame
Definition types.h:164
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
Definition types.h:167
This is an umbrella header for video functions.
bool vc_deinterlace_ex(codec_t codec, unsigned char *src, size_t src_linesize, unsigned char *dst, size_t dst_pitch, size_t lines)
bool video_desc_eq_excl_param(struct video_desc a, struct video_desc b, unsigned int excluded_params)
Compares two video descriptions.
#define VIDEO_FRAME_DISPOSE(frame)
Definition video_frame.h:76
#define PARAM_INTERLACING
Definition video_frame.h:66
#define VO_PP_ABI_VERSION