UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
ipc_frame_ug.cpp
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#include "config_unix.h"
4#include "config_win32.h"
5#include "debug.h"
6#endif
7
8#include <array>
9#include <cmath>
10#include <vector>
11
12#include "ipc_frame_ug.h"
13#include "ipc_frame.h"
14#include "pixfmt_conv.h"
15#include "types.h"
16#include "video_codec.h"
17
18namespace {
19void scale_frame(char *dst, char *src,
20 int src_w, int src_h,
21 int f, codec_t codec)
22{
23 int src_line_len = vc_get_linesize(src_w, codec);
24 int block_size = get_pf_block_bytes(codec);
25 assert(block_size > 0);
26 int blocks_per_line = src_line_len / block_size / f;
27 int dst_line_len = vc_get_linesize(blocks_per_line * get_pf_block_pixels(codec), codec);
28 int out_lines = 0;
29 for(int y = 0; y + f <= src_h; y += f){
30 int written = 0;
31 for(int x = 0; x + f * block_size <= src_line_len; x += f * block_size){
32 memcpy(dst + out_lines * dst_line_len + written, src + y*src_line_len + x, block_size);
33 written += block_size;
34 }
35 out_lines++;
36 }
37}
38
39}//anon namespace
40
42 const struct video_frame *src,
44 unsigned scale_factor)
45{
46 assert(codec == RGB);
47
48 if(!src)
49 return false;
50
52 if(!dec){
53 return false;
54 }
55
56 dst->header.width = src->tiles[0].width;
57 dst->header.height = src->tiles[0].height;
58 dst->header.color_spec = static_cast<Ipc_frame_color_spec>(codec);
59
60 if(scale_factor != 0){
61 int block_size_px = get_pf_block_pixels(codec);
62 int block_count = (dst->header.width + block_size_px - 1) / block_size_px;
63 dst->header.width = (block_count / scale_factor) * block_size_px;
64 dst->header.height /= scale_factor;
65 }
66
67 int dst_frame_size = get_bpp(codec) * dst->header.width * dst->header.height;
68 if(!ipc_frame_reserve(dst, dst_frame_size))
69 return false;
70
71 dst->header.data_len = dst_frame_size;
72
73 char *scale_src = nullptr;
74 std::vector<unsigned char> rgb_frame;
75
76 if(dec == vc_memcpy)
77 scale_src = src->tiles[0].data;
78 else{
79 auto rgb_line_len = vc_get_linesize(src->tiles[0].width, codec);
80 unsigned char *dec_dst = nullptr;
81 if(scale_factor != 0){
82 rgb_frame.resize(rgb_line_len * src->tiles[0].height);
83 scale_src = (char *) rgb_frame.data();
84 dec_dst = (unsigned char *) scale_src;
85 } else {
86 dec_dst = (unsigned char *) dst->data;
87 }
88
89 for(unsigned i = 0; i < src->tiles[0].height; i++){
90 dec(dec_dst + rgb_line_len * i,
91 (unsigned char *) src->tiles[0].data + vc_get_linesize(src->tiles[0].width, src->color_spec) * i,
92 rgb_line_len,
93 0, 8, 16);
94 }
95 }
96
97 if(scale_factor == 0)
98 return true;
99
100 scale_frame(dst->data, scale_src,
101 src->tiles[0].width, src->tiles[0].height,
102 scale_factor, codec);
103
104 return true;
105}
106
108 const struct video_frame *src,
110 unsigned scale_factor)
111{
112 if(!src)
113 return false;
114
115 decoder_t dec = nullptr;
116 if(codec != VIDEO_CODEC_NONE){
118 if(!dec){
119 return false;
120 }
121 } else {
122 codec = src->color_spec;
123 dec = vc_memcpy;
124 }
125
126 dst->header.width = src->tiles[0].width;
127 dst->header.height = src->tiles[0].height;
128 dst->header.color_spec = static_cast<Ipc_frame_color_spec>(codec);
129
130 int dst_frame_to_allocate = 0;
131
132 if(scale_factor != 0){
133 int block_size_px = get_pf_block_pixels(src->color_spec);
134 int block_count = (dst->header.width + block_size_px - 1) / block_size_px;
135 dst->header.width = (block_count / scale_factor) * block_size_px;
136 dst->header.height /= scale_factor;
137
138 if(dec != vc_memcpy){
139 //When both scaling and converting we need a tmp space - allocate extra
140 dst_frame_to_allocate += vc_get_linesize(dst->header.width, src->color_spec) * dst->header.height;
141 }
142 }
143
144 int dst_frame_size = get_bpp(codec) * dst->header.width * dst->header.height;
145 dst_frame_to_allocate += dst_frame_size;
146
147 if(!ipc_frame_reserve(dst, dst_frame_to_allocate))
148 return false;
149
150 dst->header.data_len = dst_frame_size;
151
152 char *scale_dst = dst->data;
153 unsigned char *dec_dst = (unsigned char *) dst->data;
154 unsigned char *dec_src = (unsigned char *) src->tiles[0].data;
155
156 if(scale_factor != 0){
157 if(dec != vc_memcpy){
158 scale_dst = dst->data + dst_frame_size;
159 }
160 dec_src = (unsigned char *) scale_dst;
161
162 scale_frame(scale_dst, src->tiles[0].data,
163 src->tiles[0].width, src->tiles[0].height,
164 scale_factor, src->color_spec);
165
166 }
167
168
169 if(dec_src == dec_dst){
170 assert(dec == vc_memcpy);
171 return true;
172 }
173
174 int dst_line_len = vc_get_linesize(dst->header.width, codec);
175 int src_line_len = vc_get_linesize(dst->header.width, src->color_spec);
176 for(int i = 0; i < dst->header.height; i++){
177 dec(dec_dst + dst_line_len * i,
178 dec_src + src_line_len * i,
179 dst_line_len,
180 0, 8, 16);
181 }
182
183 return true;
184}
185
186int ipc_frame_get_scale_factor(int src_w, int src_h, int target_w, int target_h){
187 if(target_w== -1 || target_h== -1)
188 return 0;
189
190 float scale = std::sqrt((static_cast<float>(src_w) * src_h)
191 / (static_cast<float>(target_w) * target_h));
192
193 if(scale < 1)
194 scale = 1;
195
196 return std::round(scale);
197}
int vc_get_linesize(unsigned int width, codec_t codec)
bool ipc_frame_reserve(Ipc_frame *frame, size_t size)
Definition ipc_frame.cpp:66
Ipc_frame_color_spec
Definition ipc_frame.h:9
bool ipc_frame_from_ug_frame_hq(struct Ipc_frame *dst, const struct video_frame *src, codec_t codec, unsigned scale_factor)
Same as ipc_frame_from_ug_frame, but convert pixfmt first and scale later.
bool ipc_frame_from_ug_frame(struct Ipc_frame *dst, const struct video_frame *src, codec_t codec, unsigned scale_factor)
Make an ipc frame from ultragrid frame.
int ipc_frame_get_scale_factor(int src_w, int src_h, int target_w, int target_h)
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
decoder_func_t vc_memcpy
dummy conversion - ptr to it returned if no conversion needed
enum Ipc_frame_color_spec color_spec
Definition ipc_frame.h:20
Ipc_frame_header header
Definition ipc_frame.h:24
char * data
Definition ipc_frame.h:25
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 height
Definition types.h:281
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
codec_t color_spec
Definition types.h:306
codec_t
Definition types.h:65
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ VIDEO_CODEC_NONE
dummy color spec
Definition types.h:66
int get_pf_block_bytes(codec_t codec)
returns codec_info_t::block_size_bytes
double get_bpp(codec_t codec)
int get_pf_block_pixels(codec_t codec)
returns codec_info_t::block_size_pixels