UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
rtpdec_h264.c
Go to the documentation of this file.
1/*
2 * AUTHOR: David Cassany <david.cassany@i2cat.net>,
3 * Ignacio Contreras <ignacio.contreras@i2cat.net>,
4 * Gerard Castillo <gerard.castillo@i2cat.net>
5 *
6 * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, is permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 *
22 * This product includes software developed by the University of Southern
23 * California Information Sciences Institute.
24 *
25 * 4. Neither the name of the University nor of the Institute may be used
26 * to endorse or promote products derived from this software without
27 * specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
31 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
33 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
34 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
39 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
40 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 */
43
44#include <assert.h> // for assert
45#include <stdbool.h> // for false, true
46#include <stdint.h> // for uint8_t, uint32_t, uint16_t
47#include <stdlib.h> // for free, malloc, NULL
48#include <string.h> // for memcpy
49
50#include "compat/htonl.h" // for ntohs
51#include "debug.h"
52#include "rtp/rtp.h"
53#include "rtp/pbuf.h"
54#include "rtp/rtpenc_h264.h" // for get_nalu_name
55#include "rtp/rtpdec_h264.h"
56#include "rtp/rtpdec_state.h"
57#include "types.h" // for tile, video_frame, frame_type
58#include "utils/h264_stream.h"
59#include "utils/bs.h"
60#include "video_frame.h"
61
63#define H264_NAL 32
64
65#define MOD_NAME "[rtpdec_h264] "
66
67static const uint8_t start_sequence[] = { 0, 0, 0, 1 };
68
69int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len);
70
81static uint8_t process_nal(uint8_t nal, struct video_frame *frame, uint8_t *data, int data_len) {
82 uint8_t type = H264_NALU_HDR_GET_TYPE(nal);
83 uint8_t nri = H264_NALU_HDR_GET_NRI(nal);
84 log_msg(LOG_LEVEL_DEBUG2, "NAL type %s (%d; nri: %d)\n",
85 get_nalu_name(type), (int) type, (int) nri);
86
87 if (type == NAL_H264_SPS) {
88 fill_coded_frame_from_sps(frame, data, data_len);
89 }
90
91 if (type >= NAL_H264_MIN && type <= NAL_H264_MAX) {
92 if (type == NAL_H264_IDR || type == NAL_H264_SEI) {
94 } else if (frame->frame_type == BFRAME && nri != 0){
96 }
97 }
98 return type;
99}
100
107static _Bool decode_nal_unit(struct video_frame *frame, int *total_length, int pass, unsigned char **dst, uint8_t *data, int data_len) {
108 int fu_length = 0;
109 uint8_t nal = data[0];
110 uint8_t type = pass == 0 ? process_nal(nal, frame, data, data_len) : H264_NALU_HDR_GET_TYPE(nal);
111 if (type >= NAL_H264_MIN && type <= NAL_H264_MAX) {
112 type = H264_NAL;
113 }
114
115 switch (type) {
116 case H264_NAL:
117 if (pass == 0) {
118 *total_length += sizeof(start_sequence) + data_len;
119 } else {
120 *dst -= data_len + sizeof(start_sequence);
121 memcpy(*dst, start_sequence, sizeof(start_sequence));
122 memcpy(*dst + sizeof(start_sequence), data, data_len);
123 }
124 break;
125 case RTP_STAP_A:
126 {
127 int nal_sizes[100];
128 unsigned nal_count = 0;
129 data++;
130 data_len--;
131
132 while (data_len > 2) {
133 uint16_t nal_size;
134 memcpy(&nal_size, data, sizeof(uint16_t));
135 nal_size = ntohs(nal_size);
136
137 data += 2;
138 data_len -= 2;
139
141 "STAP-A subpacket NAL type %d (nri: %d)\n",
142 (int) H264_NALU_HDR_GET_TYPE(data[0]),
143 (int) H264_NALU_HDR_GET_NRI(nal));
144
145 if (nal_size <= data_len) {
146 if (pass == 0) {
147 *total_length += sizeof(start_sequence) + nal_size;
148 process_nal(data[0], frame, data, data_len);
149 } else {
150 assert(nal_count < sizeof nal_sizes / sizeof nal_sizes[0] - 1);
151 nal_sizes[nal_count++] = nal_size;
152 }
153 } else {
154 error_msg("NAL size exceeds length: %u %d\n", nal_size, data_len);
155 return false;
156 }
157 data += nal_size;
158 data_len -= nal_size;
159
160 if (data_len < 0) {
161 error_msg("Consumed more bytes than we got! (%d)\n", data_len);
162 return false;
163 }
164
165 }
166 if (pass > 0) {
167 for (int i = nal_count - 1; i >= 0; i--) {
168 int nal_size = nal_sizes[i];
169 data -= nal_size;
170 *dst -= nal_size + sizeof(start_sequence);
171 memcpy(*dst, start_sequence, sizeof(start_sequence));
172 memcpy(*dst + sizeof(start_sequence), data, nal_size);
173 data -= 2;
174 }
175 }
176 break;
177 }
178 case RTP_STAP_B:
179 case RTP_MTAP16:
180 case RTP_MTAP24:
181 case RTP_FU_B:
182 error_msg("Unhandled NAL type %d\n", type);
183 return false;
184 case RTP_FU_A:
185 data++;
186 data_len--;
187
188 if (data_len > 1) {
189 uint8_t fu_header = *data;
190 uint8_t start_bit = fu_header >> 7;
191 uint8_t end_bit = (fu_header & 0x40) >> 6;
192 uint8_t nal_type = H264_NALU_HDR_GET_TYPE(fu_header);
193 uint8_t reconstructed_nal;
194
195 // Reconstruct this packet's true nal; only the data follows.
196 /* The original nal forbidden bit and NRI are stored in this
197 * packet's nal. */
198 reconstructed_nal = nal & 0xe0;
199 reconstructed_nal |= nal_type;
200
201 // skip the fu_header
202 data++;
203 data_len--;
204
205 if (pass == 0) {
206 if (end_bit) {
207 fu_length = data_len;
208 } else {
209 fu_length += data_len;
210 }
211 if (start_bit) {
212 *total_length += sizeof(start_sequence) + sizeof(reconstructed_nal) + data_len;
213 process_nal(reconstructed_nal, frame, data, fu_length);
214 } else {
215 *total_length += data_len;
216 }
217 } else {
218 if (start_bit) {
219 *dst -= sizeof(start_sequence) + sizeof(reconstructed_nal) + data_len;
220 memcpy(*dst, start_sequence, sizeof(start_sequence));
221 memcpy(*dst + sizeof(start_sequence), &reconstructed_nal, sizeof(reconstructed_nal));
222 memcpy(*dst + sizeof(start_sequence) + sizeof(reconstructed_nal), data, data_len);
223 } else {
224 *dst -= data_len;
225 memcpy(*dst, data, data_len);
226 }
227 }
228 } else {
229 error_msg("Too short data for FU-A H264 RTP packet\n");
230 return false;
231 }
232 break;
233 default:
234 error_msg("Unknown NAL type %d\n", type);
235 return false;
236 }
237 return true;
238}
239
240static void
241write_sps_pps(struct video_frame *frame, struct decode_data_rtsp *decode_data) {
242 memcpy(frame->tiles[0].data, decode_data->h264.offset_buffer,
243 decode_data->offset_len);
244}
245
253struct video_frame *
255 struct decode_data_rtsp *decode_data)
256{
257 if (decode_data->offset_len == 0) {
258 return NULL;
259 }
261 frame->tiles[0].data_len = decode_data->offset_len;
263 write_sps_pps(frame, decode_data);
264 return frame;
265}
266
267int decode_frame_h264(struct coded_data *cdata, void *decode_data) {
268 struct coded_data *orig = cdata;
269
270 int total_length = 0;
271
272 struct decode_data_rtsp *data = decode_data;
273 struct video_frame *frame = data->frame;
275
276 for (int pass = 0; pass < 2; pass++) {
277 unsigned char *dst = NULL;
278
279 if (pass > 0) {
280 cdata = orig;
281 if(frame->frame_type == INTRA){
282 total_length+=data->offset_len;
283 }
284 frame->tiles[0].data_len = total_length;
285 assert(frame->tiles[0].data == NULL);
286 frame->tiles[0].data = malloc(total_length);
288 dst = (unsigned char *) frame->tiles[0].data + total_length;
289 }
290
291 while (cdata != NULL) {
292 rtp_packet *pckt = cdata->data;
293
294 if (!decode_nal_unit(frame, &total_length, pass, &dst, (uint8_t *) pckt->data, pckt->data_len)) {
295 return false;
296 }
297
298 cdata = cdata->nxt;
299 }
300 }
301
302 if (frame->frame_type == INTRA) {
303 write_sps_pps(frame, data);
304 }
305
306 return true;
307}
308
309int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len){
310 uint32_t width, height;
311 sps_t* sps = (sps_t*)malloc(sizeof(sps_t));
312 uint8_t* rbsp_buf = (uint8_t*)malloc(data_len);
313 if (nal_to_rbsp(data, &data_len, rbsp_buf, &data_len) < 0){
314 free(rbsp_buf);
315 free(sps);
316 return -1;
317 }
318 bs_t* b = bs_new(rbsp_buf, data_len);
319 if(read_seq_parameter_set_rbsp(sps,b) < 0){
320 bs_free(b);
321 free(rbsp_buf);
322 free(sps);
323 return -1;
324 }
325 width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
326 height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1) * 16;
327 //NOTE: frame_mbs_only_flag = 1 --> only progressive frames
328 // frame_mbs_only_flag = 0 --> some type of interlacing (there are 3 types contemplated in the standard)
329 if (sps->frame_cropping_flag){
330 width -= (sps->frame_crop_left_offset*2 + sps->frame_crop_right_offset*2);
331 height -= (sps->frame_crop_top_offset*2 + sps->frame_crop_bottom_offset*2);
332 }
333
334 if((width != rx_data->tiles[0].width) || (height != rx_data->tiles[0].height)) {
335 vf_get_tile(rx_data, 0)->width = width;
336 vf_get_tile(rx_data, 0)->height = height;
337// free(rx_data->tiles[0].data);
338// rx_data->tiles[0].data = calloc(1, rx_data->h264_width * rx_data->h264_height);
339 }
340
341 bs_free(b);
342 free(rbsp_buf);
343 free(sps);
344
345 return 0;
346}
347
348int width_height_from_SDP(int *widthOut, int *heightOut , unsigned char *data, int data_len){
349 uint32_t width, height;
350 sps_t* sps = (sps_t*)malloc(sizeof(sps_t));
351 uint8_t* rbsp_buf = (uint8_t*)malloc(data_len);
352 if (nal_to_rbsp(data, &data_len, rbsp_buf, &data_len) < 0){
353 free(rbsp_buf);
354 free(sps);
355 return -1;
356 }
357 bs_t* b = bs_new(rbsp_buf, data_len);
358 if(read_seq_parameter_set_rbsp(sps,b) < 0){
359 bs_free(b);
360 free(rbsp_buf);
361 free(sps);
362 return -1;
363 }
364 width = (sps->pic_width_in_mbs_minus1 + 1) * 16;
365 height = (2 - sps->frame_mbs_only_flag) * (sps->pic_height_in_map_units_minus1 + 1) * 16;
366 //NOTE: frame_mbs_only_flag = 1 --> only progressive frames
367 // frame_mbs_only_flag = 0 --> some type of interlacing (there are 3 types contemplated in the standard)
368 if (sps->frame_cropping_flag){
369 width -= (sps->frame_crop_left_offset*2 + sps->frame_crop_right_offset*2);
370 height -= (sps->frame_crop_top_offset*2 + sps->frame_crop_bottom_offset*2);
371 }
372
373 debug_msg("\n\n[width_height_from_SDP] width: %d height: %d\n\n",width,height);
374
375
376 if(width > 0){
377 *widthOut = width;
378 }
379 if(height > 0){
380 *heightOut = height;
381 }
382
383 bs_free(b);
384 free(rbsp_buf);
385 free(sps);
386
387 return 0;
388}
389
390// vi: set et sw=4 :
struct video_desc desc
struct video_frame * frame
void vf_free(struct video_frame *buf)
Frees video_frame structure.
void vf_data_deleter(struct video_frame *buf)
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
static void bs_free(bs_t *b)
Definition bs.h:97
static bs_t * bs_new(uint8_t *buf, size_t size)
Definition bs.h:90
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define error_msg(...)
Definition debug.h:89
#define LOG_LEVEL_DEBUG2
Definition debug.h:67
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
Definition debug.h:92
int nal_to_rbsp(const uint8_t *nal_buf, int *nal_size, uint8_t *rbsp_buf, int *rbsp_size)
Definition h264_stream.c:51
int read_seq_parameter_set_rbsp(sps_t *sps, bs_t *b)
rtp_packet
Definition rtp.h:126
int width_height_from_SDP(int *widthOut, int *heightOut, unsigned char *data, int data_len)
#define H264_NAL
type was 1-23 representing H.264 NAL type
Definition rtpdec_h264.c:63
static const uint8_t start_sequence[]
Definition rtpdec_h264.c:67
static _Bool decode_nal_unit(struct video_frame *frame, int *total_length, int pass, unsigned char **dst, uint8_t *data, int data_len)
int decode_frame_h264(struct coded_data *cdata, void *decode_data)
static uint8_t process_nal(uint8_t nal, struct video_frame *frame, uint8_t *data, int data_len)
Definition rtpdec_h264.c:81
int fill_coded_frame_from_sps(struct video_frame *rx_data, unsigned char *data, int data_len)
static void write_sps_pps(struct video_frame *frame, struct decode_data_rtsp *decode_data)
struct video_frame * get_sps_pps_frame(const struct video_desc *desc, struct decode_data_rtsp *decode_data)
@ RTP_MTAP16
Definition rtpdec_h264.h:76
@ RTP_STAP_B
Definition rtpdec_h264.h:75
@ RTP_MTAP24
Definition rtpdec_h264.h:77
@ RTP_FU_B
Definition rtpdec_h264.h:79
@ RTP_FU_A
Definition rtpdec_h264.h:78
@ RTP_STAP_A
Definition rtpdec_h264.h:74
#define H264_NALU_HDR_GET_TYPE(nal)
Definition rtpdec_h264.h:86
#define H264_NALU_HDR_GET_NRI(nal)
Definition rtpdec_h264.h:87
@ NAL_H264_MAX
Definition rtpdec_h264.h:54
@ NAL_H264_MIN
Definition rtpdec_h264.h:53
nal_type
Definition rtpdec_h264.h:57
@ NAL_H264_IDR
Definition rtpdec_h264.h:60
@ NAL_H264_SPS
Definition rtpdec_h264.h:62
@ NAL_H264_SEI
Definition rtpdec_h264.h:61
const char * get_nalu_name(int type)
Option::OptType type
Definition settings.cpp:194
Definition bs.h:35
rtp_packet * data
Definition pbuf.h:75
struct coded_data * nxt
Definition pbuf.h:72
struct decode_data_rtsp::@46::@48 h264
struct video_frame * frame
unsigned char offset_buffer[2048]
SPS/PPS headers extracted from RTSP.
int frame_crop_right_offset
Definition h264_stream.h:83
int frame_crop_left_offset
Definition h264_stream.h:82
int pic_height_in_map_units_minus1
Definition h264_stream.h:77
int frame_cropping_flag
Definition h264_stream.h:81
int frame_crop_top_offset
Definition h264_stream.h:84
int frame_crop_bottom_offset
Definition h264_stream.h:85
int pic_width_in_mbs_minus1
Definition h264_stream.h:76
int frame_mbs_only_flag
Definition h264_stream.h:78
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
void(* data_deleter)(struct video_frame *)
Definition types.h:256
void(* dispose)(struct video_frame *)
Definition types.h:245
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
frame_type_t frame_type
Definition types.h:309
struct video_frame_callbacks callbacks
Definition types.h:324
@ INTRA
Definition types.h:195
@ BFRAME
Definition types.h:196
@ OTHER
Definition types.h:197
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].