//7.3.2.3 Supplemental enhancement information RBSP syntax void structure(sei_rbsp)(h264_stream_t* h, bs_t* b) { if( is_reading ) { for( int i = 0; i < h->num_seis; i++ ) { sei_free(h->seis[i]); } h->num_seis = 0; do { h->num_seis++; h->seis = (sei_t**)realloc(h->seis, h->num_seis * sizeof(sei_t*)); h->seis[h->num_seis - 1] = sei_new(); h->sei = h->seis[h->num_seis - 1]; structure(sei_message)(h, b); } while( more_rbsp_data(h, b) ); } if( is_writing ) { for (int i = 0; i < h->num_seis; i++) { h->sei = h->seis[i]; structure(sei_message)(h, b); } h->sei = NULL; } structure(rbsp_trailing_bits)(h, b); }
/** Free an existing H264 stream object. Frees all contained structures. @param[in,out] h the stream object */ void h264_free(h264_stream_t* h) { free(h->nal); for ( int i = 0; i < 32; i++ ) { free( h->sps_table[i] ); } for ( int i = 0; i < 256; i++ ) { free( h->pps_table[i] ); } free(h->aud); if(h->seis != NULL) { for( int i = 0; i < h->num_seis; i++ ) { sei_t* sei = h->seis[i]; sei_free(sei); } free(h->seis); } free(h->sh); if (h->slice_data) { if (h->slice_data->rbsp_buf) free(h->slice_data->rbsp_buf); free(h->slice_data); } free(h); }
size_t mpeg_bitstream_parse(mpeg_bitstream_t* packet, caption_frame_t* frame, const uint8_t* data, size_t size, unsigned stream_type, double dts, double cts) { if (MAX_NALU_SIZE <= packet->size) { packet->status = LIBCAPTION_ERROR; // fprintf(stderr, "LIBCAPTION_ERROR\n"); return 0; } // consume upto MAX_NALU_SIZE bytes if (MAX_NALU_SIZE <= packet->size + size) { size = MAX_NALU_SIZE - packet->size; } sei_t sei; size_t header_size, scpos; packet->status = LIBCAPTION_OK; memcpy(&packet->data[packet->size], data, size); packet->size += size; while (packet->status == LIBCAPTION_OK && 0 < (scpos = find_start_code(&packet->data[0], packet->size))) { switch (mpeg_bitstream_packet_type(packet, stream_type)) { default: break; case H262_SEI_PACKET: header_size = 4; if (STREAM_TYPE_H262 == stream_type && scpos > header_size) { cea708_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts); packet->status = libcaption_status_update(packet->status, cea708_parse_h262(&packet->data[header_size], scpos - header_size, cea708)); _mpeg_bitstream_cea708_sort_flush(packet, frame, dts); } break; case H264_SEI_PACKET: case H265_SEI_PACKET: header_size = STREAM_TYPE_H264 == stream_type ? 4 : STREAM_TYPE_H265 == stream_type ? 5 : 0; if (header_size && scpos > header_size) { packet->status = libcaption_status_update(packet->status, sei_parse(&sei, &packet->data[header_size], scpos - header_size, dts + cts)); for (sei_message_t* msg = sei_message_head(&sei); msg; msg = sei_message_next(msg)) { if (sei_type_user_data_registered_itu_t_t35 == sei_message_type(msg)) { cea708_t* cea708 = _mpeg_bitstream_cea708_emplace_back(packet, dts + cts); packet->status = libcaption_status_update(packet->status, cea708_parse_h264(sei_message_data(msg), sei_message_size(msg), cea708)); _mpeg_bitstream_cea708_sort_flush(packet, frame, dts); } } sei_free(&sei); } break; } packet->size -= scpos; memmove(&packet->data[0], &packet->data[scpos], packet->size); } return size; }
/** Free an existing H264 stream object. Frees all contained structures. @param[in,out] h the stream object */ void h264_free(h264_stream_t* h) { free(h->nal->nal_svc_ext); free(h->nal->prefix_nal_svc); free(h->nal); for ( int i = 0; i < 32; i++ ) { free( h->sps_table[i] ); } for ( int i = 0; i < 64; i++ ) { if( h->sps_subset_table[i]->sps != NULL ) free( h->sps_subset_table[i]->sps ); if( h->sps_subset_table[i]->sps_svc_ext != NULL ) free( h->sps_subset_table[i]->sps_svc_ext ); free( h->sps_subset_table[i] ); } for ( int i = 0; i < 256; i++ ) { free( h->pps_table[i] ); } free(h->pps); free(h->aud); if(h->seis != NULL) { for( int i = 0; i < h->num_seis; i++ ) { sei_t* sei = h->seis[i]; sei_free(sei); } free(h->seis); } free(h->sh); if (h->sh_svc_ext != NULL) free(h->sh_svc_ext); if (h->slice_data != NULL) { if (h->slice_data->rbsp_buf != NULL) { free(h->slice_data->rbsp_buf); } free(h->slice_data); } free(h->sps); free(h->sps_subset->sps); free(h->sps_subset->sps_svc_ext); free(h->sps_subset); free(h); }