ref: 73ef8b16fe03183346cd1272d0ed4d15028cb104
parent: 3296f28705a08bd9daff92a677b0fa76098941dd
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Tue May 2 22:39:58 EDT 2023
garbage ivf-h264-extractor tool
--- /dev/null
+++ b/ivfh264.c
@@ -1,0 +1,849 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "vpuctx.h"
+
+enum {
+ Extended_SAR = 255,
+};
+
+typedef struct Bits Bits;
+typedef struct Bitspos Bitspos;
+typedef struct nal_unit_header_svc_extension nal_unit_header_svc_extension;
+typedef struct nal_unit_header_mvc_extension nal_unit_header_mvc_extension;
+
+struct Bitspos {
+ vlong boff;
+ u64int p;
+ int c;
+ int nb;
+ int nz;
+ int eof;
+};
+
+struct Bits {
+ Bitspos;
+ Biobuf *b;
+};
+
+struct nal_unit_header_svc_extension {
+ u8int idr_flag;
+ u8int priority_id;
+ u8int no_inter_layer_pred_flag;
+ u8int dependency_id;
+ u8int quality_id;
+ u8int temporal_id;
+ u8int use_ref_base_pic_flag;
+ u8int discardable_flag;
+ u8int output_flag;
+ u8int reserved_three_2bits;
+};
+
+struct nal_unit_header_mvc_extension {
+ u8int non_idr_flag;
+ u8int priority_id;
+ u16int view_id;
+ u8int temporal_id;
+ u8int anchor_pic_flag;
+ u8int inter_view_flag;
+ u8int reserved_one_bit;
+};
+
+#define Default_4x4_Intra {6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42}
+#define Default_4x4_Inter {10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}
+#define Default_8x8_Intra \
+ {6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 23, \
+ 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, \
+ 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, \
+ 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42}
+#define Default_8x8_Inter \
+ {9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, \
+ 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, \
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, \
+ 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35}
+
+static u8int defsl4x4[6][16] = {
+ Default_4x4_Intra, /* Sl_4x4_Intra_Y */
+ Default_4x4_Intra, /* Sl_4x4_Intra_Cb */
+ Default_4x4_Intra, /* Sl_4x4_Intra_Cr */
+ Default_4x4_Inter, /* Sl_4x4_Inter_Y */
+ Default_4x4_Inter, /* Sl_4x4_Inter_Cb */
+ Default_4x4_Inter, /* Sl_4x4_Inter_Cr */
+};
+
+static u8int defs8x8[6][64] = {
+ Default_8x8_Intra, /* Sl_8x8_Intra_Y */
+ Default_8x8_Inter, /* Sl_8x8_Inter_Y */
+ Default_8x8_Intra, /* Sl_8x8_Intra_Cb */
+ Default_8x8_Inter, /* Sl_8x8_Inter_Cb */
+ Default_8x8_Intra, /* Sl_8x8_Intra_Cr */
+ Default_8x8_Inter, /* Sl_8x8_Inter_Cr */
+};
+
+static Biobuf stdout;
+
+static int
+clz(u32int x)
+{
+ int r;
+ if(x == 0)
+ return 0;
+ for(r = 0; (x & (1U<<31)) == 0; x <<= 1, r++);
+ return r;
+}
+
+#define ceillog2(x) (32-clz(x))
+
+void
+mark(Bits *b, Bitspos *pos)
+{
+ *pos = b->Bitspos;
+ pos->boff = Boffset(b->b);
+}
+
+void
+unroll(Bits *b, Bitspos *pos)
+{
+ while(Boffset(b->b) != pos->boff){
+ if(Bungetc(b->b) < 0)
+ sysfatal("Bungetc\n");
+ }
+ b->Bitspos = *pos;
+}
+
+u32int
+rb_u(Bits *b, int n, char *s)
+{
+ int m;
+ u32int x;
+
+ if(n == 0)
+ return 0;
+
+ if(s != nil)
+ Bprint(&stdout, "%llud\t%s = ", b->p, s);
+ x = 0;
+ for(; n > 0; n -= m, b->p += m){
+ if(b->nb == 0){
+again:
+ if((b->c = Bgetc(b->b)) == Beof){
+ b->eof = 1;
+ return -1;
+ }
+ if(b->nz == 2 && b->c == 3){
+ b->nz = 0;
+ goto again;
+ }
+ b->nz = b->c == 0 ? b->nz+1 : 0;
+ b->nb = 8;
+ }
+
+ if((m = n) > b->nb)
+ m = b->nb;
+ x <<= m;
+ x |= (b->c >> b->nb-m) & (1<<m)-1;
+ b->nb -= m;
+ }
+ if(s != nil)
+ Bprint(&stdout, "%ud\n", x);
+ return x;
+}
+
+u32int
+rb_ue(Bits *b, char *s)
+{
+ u32int x;
+ int n;
+
+ if(s != nil)
+ Bprint(&stdout, "%llud\t%s = ", b->p, s);
+ for(n = 0; rb_u(b, 1, nil) == 0 && n < 32 && !b->eof; n++);
+ x = rb_u(b, n, nil) + (1<<n) - 1;
+ if(s != nil)
+ Bprint(&stdout, "%ud\n", x);
+ return x;
+}
+
+int
+rb_se(Bits *b, char *s)
+{
+ int x;
+ if(s != nil)
+ Bprint(&stdout, "%llud\t%s = ", b->p, s);
+ x = rb_ue(b, nil);
+ x = ((x & 1) == 0 ? -x : x+1) >> 1;
+ if(s != nil)
+ Bprint(&stdout, "%d\n", x);
+ return x;
+}
+
+#define u(n, s) rb_u(b, n, s)
+#define ue(s) rb_ue(b, s)
+#define se(s) rb_se(b, s)
+
+static void
+hrd_parameters(VPUctx *v, Bits *b)
+{
+ int i, n;
+
+ USED(v);
+ n = ue("cpb_cnt_minus1");
+ u(4, "bit_rate_scale");
+ u(4, "cpb_size_scale");
+ for(i = 0; i < n; i++){
+ char t[32];
+ snprint(t, sizeof(t), "bit_rate_value_minus1[%d]", i);
+ ue(t);
+ snprint(t, sizeof(t), "cpb_size_value_minus1[%d]", i);
+ ue(t);
+ snprint(t, sizeof(t), "cbr_flag[%d]", i);
+ u(1, t);
+ }
+ u(5, "initial_cpb_removal_delay_length_minus1");
+ u(5, "cpb_removal_delay_length_minus1");
+ u(5, "dpb_output_delay_length_minus1");
+ u(5, "time_offset_length");
+}
+
+static void
+scaling_list(VPUctx *v, Bits *b, int i)
+{
+ u8int *scalingList;
+ int f, j, lastScale, nextScale, sizeOfScalingList, delta_scale;
+
+ lastScale = nextScale = 8;
+ if(i < 6){
+ sizeOfScalingList = 16;
+ scalingList = &v->sl4x4[i*sizeOfScalingList];
+ }else{
+ sizeOfScalingList = 64;
+ scalingList = &v->sl8x8[(i-6)*sizeOfScalingList];
+ }
+ for(j = 0; j < sizeOfScalingList; j++){
+ if(nextScale != 0){
+ delta_scale = se("delta_scale");
+ nextScale = (lastScale + delta_scale + 256) % 256;
+ f = (j == 0 && nextScale == 0) << j;
+ v->useDefaultScalingMatrixFlag &= ~f;
+ v->useDefaultScalingMatrixFlag |= f;
+ }
+ lastScale = scalingList[j] = nextScale == 0 ? lastScale : nextScale;
+ }
+}
+
+static void
+vui_parameters(VPUctx *v, Bits *b)
+{
+ int n;
+
+ if(u(1, "aspect_ratio_info_present_flag")){
+ n = u(8, "aspect_ratio_idc");
+ if(n == Extended_SAR){
+ u(16, "sar_width");
+ u(16, "sar_height");
+ }
+ }
+ if(u(1, "overscan_info_present_flag"))
+ u(1, "overscan_appropriate_flag");
+ if(u(1, "video_signal_type_present_flag")){
+ u(3, "video_format");
+ u(1, "video_full_range_flag");
+ if(u(1, "colour_description_present_flag")){
+ u(8, "color_primaries");
+ u(8, "transfer_characteristics");
+ u(8, "matrix_coefficients");
+ }
+ }
+ if(u(1, "chroma_loc_info_present_flag")){
+ ue("chroma_sample_loc_type_top_field");
+ ue("chroma_sample_loc_type_bottom_field");
+ }
+ if(u(1, "timing_info_present_flag")){
+ u(32, "num_units_in_tick");
+ u(32, "time_scale");
+ u(1, "fixed_frame_rate_flag");
+ }
+ if((n = u(1, "nal_hrd_parameters_present_flag")))
+ hrd_parameters(v, b);
+ if((n |= u(1, "vcl_hrd_parameters_present_flag")))
+ hrd_parameters(v, b);
+ if(n != 0)
+ u(1, "low_delay_hrd_flag");
+ u(1, "pic_struct_present_flag");
+ if(u(1, "bitstream_restriction_flag")){
+ u(1, "motion_vectors_over_pic_boundaries_flag");
+ ue("max_bytes_per_pic_denom");
+ ue("max_bits_per_mb_denom");
+ ue("log2_max_mv_length_horizontal");
+ ue("log2_max_mv_length_vertical");
+ ue("max_num_reorder_frames");
+ ue("max_dec_frame_buffering");
+ }
+}
+
+static void
+rbsp_trailing_bits(Bits *b)
+{
+ u(1, "rbsp_stop_one_bit");
+ u(8 - (b->p & 7), "rbsp_alignment_zero_bit");
+}
+
+static int
+more_rbsp_data(Bits *b)
+{
+ Bitspos pos;
+ int more;
+
+ mark(b, &pos);
+ more = u(1, nil) == 0 || u(8 - (b->p & 7), nil) != 0;
+ unroll(b, &pos);
+ return more;
+}
+
+static u32int
+next_bits(Bits *b, int n)
+{
+ Bitspos pos;
+ u32int x;
+
+ mark(b, &pos);
+ x = u(n, nil);
+ unroll(b, &pos);
+ return x;
+}
+
+static void
+unit_header_svc_extension(VPUctx *v, Bits *b)
+{
+ nal_unit_header_svc_extension e;
+
+ USED(v);
+ Bprint(&stdout, "nal_unit_header_svc_extension()\n");
+ e.idr_flag = u(1, "idr_flag");
+ e.priority_id = u(6, "priority_id");
+ e.no_inter_layer_pred_flag = u(1, "no_inter_layer_pred_flag");
+ e.dependency_id = u(3, "dependency_id");
+ e.quality_id = u(4, "quality_id");
+ e.temporal_id = u(3, "temporal_id");
+ e.use_ref_base_pic_flag = u(1, "use_ref_base_pic_flag");
+ e.discardable_flag = u(1, "discardable_flag");
+ e.output_flag = u(1, "output_flag");
+ e.reserved_three_2bits = u(2, "reserved_three_2bits");
+}
+
+static void
+unit_header_mvc_extension(VPUctx *v, Bits *b)
+{
+ nal_unit_header_mvc_extension e;
+
+ USED(v);
+ Bprint(&stdout, "nal_unit_header_mvc_extension()\n");
+ e.non_idr_flag = u(1, "non_idr_flag");
+ e.priority_id = u(6, "priority_id");
+ e.view_id = u(10, "view_id");
+ e.temporal_id = u(3, "temporal_id");
+ e.anchor_pic_flag = u(1, "anchor_pic_flag");
+ e.inter_view_flag = u(1, "inter_view_flag");
+ e.reserved_one_bit = u(1, "reserved_one_bit");
+}
+
+static int
+more_rbsp_trailing_data(Bits *b)
+{
+ USED(b);
+ assert(nil);
+ return 0;
+}
+
+static void
+rbsp_slice_trailing_bits(VPUctx *v, Bits *b)
+{
+ rbsp_trailing_bits(b);
+ if(v->pps.entropy_coding_mode_flag){
+ while(more_rbsp_trailing_data(b))
+ u(16, "cabac_zero_word");
+ }
+}
+
+static void
+slice_header(VPUctx *v, Bits *b)
+{
+ u64int p;
+
+ Bprint(&stdout, "slice_header()\n");
+ ue("first_mb_in_slice");
+ ue("slice_type"); /* % 5 */
+ ue("pic_parameter_set_id");
+ if(v->sps.separate_colour_plane_flag)
+ u(2, "colour_plane_id");
+ v->sh.frame_num = u(v->sps.log2_max_frame_num_minus4 + 4, "frame_num");
+
+ v->sh.field_pic_flag = 0;
+ v->sh.bottom_field_flag = 0;
+ if(!v->sps.frame_mbs_only_flag){
+ if((v->sh.field_pic_flag = u(1, "field_pic_flag")) != 0)
+ v->sh.bottom_field_flag = u(1, "bottom_field_flag");
+ }
+
+ if(v->nal_unit_type == 5)
+ v->sh.idr_pic_id = ue("idr_pic_id");
+
+ v->sh.size_pic_order_cnt_lsb = 0;
+ v->sh.size_delta_pic_order_cnt_bottom = 0;
+ if(v->sps.pic_order_cnt_type == 0){
+ v->sh.size_pic_order_cnt_lsb = v->sps.log2_max_pic_order_cnt_lsb_minus4 + 4;
+ u(v->sh.size_pic_order_cnt_lsb, "pic_order_cnt_lsb");
+ if(v->pps.bottom_field_pic_order_in_frame_present_flag && !v->sh.field_pic_flag){
+ p = b->p;
+ se("delta_pic_order_cnt_bottom");
+ v->sh.size_delta_pic_order_cnt_bottom = b->p - p;
+ }
+ }
+
+ v->sh.size_delta_pic_order_cnt0 = 0;
+ v->sh.size_delta_pic_order_cnt1 = 0;
+ if(v->sps.pic_order_cnt_type == 1 && !v->sps.delta_pic_order_always_zero_flag){
+ p = b->p;
+ se("delta_pic_order_cnt[0]");
+ v->sh.size_delta_pic_order_cnt0 = b->p - p;
+ if(v->pps.bottom_field_pic_order_in_frame_present_flag && !v->sh.field_pic_flag){
+ p = b->p;
+ se("delta_pic_order_cnt[1]");
+ v->sh.size_delta_pic_order_cnt1 = b->p - p;
+ }
+ }
+ /* the rest isn't needed for VPU decoding */
+}
+
+static void
+slice_layer_without_partitioning_rbsp(VPUctx *v, Bits *b)
+{
+ Bprint(&stdout, "slice_layer_without_partitioning_rbsp()\n");
+
+ slice_header(v, b);
+ /* the rest isn't needed for VPU decoding */
+}
+
+static void
+sei_rbsp(VPUctx *v, Bits *b)
+{
+ int payloadType, payloadSize, i, n;
+
+ USED(v);
+ Bprint(&stdout, "sei_rbps()\n");
+ do{
+ Bprint(&stdout, "sei_message()\n");
+ payloadType = 0;
+ while(1){
+ Bprint(&stdout, "%lld\t", b->p);
+ n = u(8, nil);
+ payloadType += n;
+ if(n != 0xff)
+ break;
+ Bprint(&stdout, "ff_byte\n");
+ }
+ Bprint(&stdout, "last_payload_type_byte = %d\n", n);
+
+ payloadSize = 0;
+ while(1){
+ Bprint(&stdout, "%lld\t", b->p);
+ n = u(8, nil);
+ payloadSize += n;
+ if(n != 0xff)
+ break;
+ Bprint(&stdout, "ff_byte\n");
+ }
+ Bprint(&stdout, "last_payload_size_byte = %d\n", n);
+
+ Bprint(&stdout, "%llud\tsei_payload(%d, %d) = ...\n", b->p, payloadType, payloadSize);
+ for(i = 0; i < payloadSize; i++)
+ u(8, nil);
+ if(b->p & 7){
+ u(1, nil);
+ u(8 - (b->p & 7), nil);
+ }
+ }while(more_rbsp_data(b));
+ rbsp_trailing_bits(b);
+}
+
+static void
+seq_parameter_set_rbsp(VPUctx *v, Bits *b)
+{
+ int i, n;
+
+ Bprint(&stdout, "seq_parameter_set_rbsp()\n");
+ v->sps.profile_idc = u(8, "profile_idc");
+ v->sps.frame_mbs_only_flag = 0;
+ for(i = 0; i < 6; i++){
+ char t[32];
+ snprint(t, sizeof(t), "constraint_set%d_flag", i);
+ if(u(1, t) && i == 4 && (v->sps.profile_idc == 77 || v->sps.profile_idc == 88 || v->sps.profile_idc == 100))
+ v->sps.frame_mbs_only_flag = 1;
+ }
+ u(2, "reserved_zero_2bits");
+ u(8, "level_idc");
+ ue("seq_parameter_set_id");
+ switch(v->sps.profile_idc){
+ case 100: case 110:
+ case 122: case 244: case 44:
+ case 83: case 86: case 118:
+ case 128: case 138: case 139:
+ case 134: case 135:
+ if((v->sps.chroma_format_idc = ue("chroma_format_idc")) == 3)
+ v->sps.separate_colour_plane_flag = u(1, "separate_colour_plane_flag");
+ ue("bit_depth_luma_minus8");
+ ue("bit_depth_chroma_minus8");
+ u(1, "qpprime_y_zero_transform_bypass_flag");
+ if((v->sps.seq_scaling_matrix_present_flag = u(1, "seq_scaling_matrix_present_flag"))){
+ for(i = 0; i < (v->sps.chroma_format_idc != 3) ? 8 : 12; i++){
+ if(u(1, "seq_scaling_list_present_flag"))
+ scaling_list(v, b, i);
+ }
+ }
+ break;
+ }
+ v->sps.log2_max_frame_num_minus4 = ue("log2_max_frame_num_minus4");
+ if((v->sps.pic_order_cnt_type = ue("pic_order_cnt_type")) == 0){
+ v->sps.log2_max_pic_order_cnt_lsb_minus4 = ue("log2_max_pic_order_cnt_lsb_minus4");
+ }else if(v->sps.pic_order_cnt_type == 1){
+ v->sps.delta_pic_order_always_zero_flag = u(1, "delta_pic_order_always_zero_flag");
+ se("offset_for_non_ref_pic");
+ se("offset_for_top_to_bottom_field");
+ n = ue("num_ref_frames_in_pic_order_cnt_cycle");
+ for(i = 0; i < n; i++){
+ char t[32];
+ snprint(t, sizeof(t), "offset_for_ref_frame[i]");
+ se(t);
+ }
+ }
+ v->sps.max_num_ref_frames = ue("max_num_ref_frames");
+ u(1, "gaps_in_frame_num_value_allowed_flag");
+ v->sps.pic_width_in_mbs_minus1 = ue("pic_width_in_mbs_minus1");
+ v->sps.pic_height_in_map_units_minus1 = ue("pic_height_in_map_units_minus1");
+ v->PicSizeInMapUnits =
+ ((int)v->sps.pic_width_in_mbs_minus1 + 1) *
+ ((int)v->sps.pic_height_in_map_units_minus1 + 1);
+ if((v->sps.frame_mbs_only_flag |= u(1, "frame_mbs_only_flag")) == 0)
+ v->sps.mb_adaptive_frame_field_flag = u(1, "mb_adaptive_frame_field_flag");
+ v->sps.direct_8x8_inference_flag = u(1, "direct_8x8_inference_flag");
+ if(u(1, "frame_cropping_flag")){
+ v->crop.left = ue("frame_crop_left_offset");
+ v->crop.right = ue("frame_crop_right_offset");
+ v->crop.top = ue("frame_crop_top_offset");
+ v->crop.bottom = ue("frame_crop_bottom_offset");
+ }
+ if(u(1, "vui_parameters_present_flag"))
+ vui_parameters(v, b);
+ rbsp_trailing_bits(b);
+}
+
+static void
+pic_parameter_set_rbsp(VPUctx *v, Bits *b)
+{
+ int i, n, x;
+
+ Bprint(&stdout, "pic_parameter_set_rbsp()\n");
+
+ v->pps.pic_parameter_set_id = ue("pic_parameter_set_id");
+ ue("seq_parameter_set_id");
+ v->pps.entropy_coding_mode_flag = u(1, "entropy_coding_mode_flag");
+ v->pps.bottom_field_pic_order_in_frame_present_flag = u(1, "bottom_field_pic_order_in_frame_present_flag");
+ if((v->pps.num_slice_groups_minus1 = ue("num_slice_groups_minus1")) > 0){
+ if((v->pps.slice_group_map_type = ue("slice_group_map_type")) == 0){
+ for(i = 0; i <= v->pps.num_slice_groups_minus1; i++){
+ char t[32];
+ snprint(t, sizeof(t), "run_length_minus1[%d]", i);
+ ue(t);
+ }
+ }else if(v->pps.slice_group_map_type == 2){
+ for(i = 0; i <= v->pps.num_slice_groups_minus1; i++){
+ char t[32];
+ snprint(t, sizeof(t), "top_left[%d]", i);
+ ue(t);
+ snprint(t, sizeof(t), "bottom_right[%d]", i);
+ ue(t);
+ }
+ }else if(v->pps.slice_group_map_type >= 3 && v->pps.slice_group_map_type <= 5){
+ u(1, "slice_group_change_direction_flag");
+ ue("slice_group_change_rate_minus1");
+ }else if(v->pps.slice_group_map_type == 6){
+ n = ue("pic_size_in_map_units_minus1");
+ x = ceillog2(v->pps.num_slice_groups_minus1 + 1);
+ for(i = 0; i <= n; i++){
+ char t[32];
+ snprint(t, sizeof(t), "slice_group_id[%d]", i);
+ u(x, t);
+ }
+ }
+ }
+ v->pps.num_ref_idx_l0_default_active_minus1 = ue("num_ref_idx_l0_default_active_minus1");
+ v->pps.num_ref_idx_l1_default_active_minus1 = ue("num_ref_idx_l1_default_active_minus1");
+ v->pps.weighted_pred_flag = u(1, "weighted_pred_flag");
+ v->pps.weighted_bipred_idc = u(2, "weighted_bipred_idc");
+ v->pps.pic_init_qp_minus26 = se("pic_init_qp_minus26");
+ se("pic_init_qs_minus26");
+ v->pps.chroma_qp_index_offset = se("chroma_qp_index_offset");
+ v->pps.deblocking_filter_control_present_flag = u(1, "deblocking_filter_control_present_flag");
+ v->pps.constrained_intra_pred_flag = u(1, "constrained_intra_pred_flag");
+ v->pps.redundant_pic_cnt_present_flag = u(1, "redundant_pic_cnt_present_flag");
+ if(more_rbsp_data(b)){
+ v->pps.transform_8x8_mode_flag = u(1, "transform_8x8_mode_flag");
+ v->pps.pic_scaling_matrix_present_flag = u(1, "pic_scaling_matrix_present_flag");
+ if(v->pps.pic_scaling_matrix_present_flag){
+ for(i = 0; i < 6 + ((v->sps.chroma_format_idc != 3) ? 2 : 6)*v->pps.transform_8x8_mode_flag; i++){
+ char t[32];
+ snprint(t, sizeof(t), "pic_scaling_list_present_flag[%d]", i);
+ if(u(1, t))
+ scaling_list(v, b, i);
+ }
+ }
+ v->pps.second_chroma_qp_index_offset = se("second_chroma_qp_index_offset");
+ }
+ rbsp_trailing_bits(b);
+}
+
+static void (*rbsp_f[])(VPUctx *v, Bits *b) = {
+ [1] = slice_layer_without_partitioning_rbsp,
+ [5] = slice_layer_without_partitioning_rbsp,
+ [6] = sei_rbsp,
+ [7] = seq_parameter_set_rbsp,
+ [8] = pic_parameter_set_rbsp,
+ [19] = slice_layer_without_partitioning_rbsp,
+};
+
+static int
+Bu16le(Biobuf *b, u16int *o)
+{
+ int x;
+
+ x = Bgetc(b);
+ x |= Bgetc(b)<<8;
+ *o = x;
+ if(x < 0)
+ werrstr("failed to read 2 bytes");
+
+ return x < 0 ? -1 : 0;
+}
+
+static int
+Bu32le(Biobuf *b, u32int *o)
+{
+ int x, i;
+
+ *o = 0;
+ for(i = 0; i < 4; *o |= x<<(i*8), i++){
+ if((x = Bgetc(b)) < 0){
+ werrstr("failed to read 4 bytes");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int
+Bu64le(Biobuf *b, u64int *o)
+{
+ int x, i;
+
+ *o = 0;
+ for(i = 0; i < 8; *o |= (uvlong)x<<(i*8), i++){
+ if((x = Bgetc(b)) < 0){
+ werrstr("failed to read 8 bytes");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void
+usage(void)
+{
+ fprint(2, "usage: %s [file.ivf]\n", argv0);
+ exits("usage");
+}
+
+static int
+decode(VPUctx *v, Bits *b, int sz)
+{
+ u32int x;
+
+ Bprint(&stdout, "@ 0x%llx [%d]\n", Boffset(b->b), sz);
+ if((x = u(24, nil)) == 0)
+ x = u(8, nil);
+ if(x != 1){
+ Bprint(&stdout, "invalid start code %02x\n", x);
+ return -1;
+ }
+
+ b->p = 0;
+ u(1, "forbidden_zero_bit");
+ v->nal_ref_idc = u(2, "nal_ref_idc");
+ v->nal_unit_type = u(5, "nal_unit_type");
+
+ if(v->nal_unit_type == 14 || v->nal_unit_type == 20){
+ if(u(1, "svc_extension_flag"))
+ unit_header_svc_extension(v, b);
+ else
+ unit_header_mvc_extension(v, b);
+ }
+
+ if(v->nal_unit_type >= nelem(rbsp_f) || rbsp_f[v->nal_unit_type] == nil)
+ Bprint(&stdout, "unexpected nal_unit_type %d", v->nal_unit_type);
+ else
+ rbsp_f[v->nal_unit_type](v, b);
+ Bprint(&stdout, "\n");
+
+ return 0;
+}
+
+void
+main(int argc, char **argv)
+{
+ u64int timestamp, framenum;
+ int fd, shgo;
+ u32int tbnum, tbdenum;
+ u16int w, h, hlen;
+ Biobuf in, settings;
+ char tmp[6], *s, *buf;
+ u32int sz;
+ VPUctx v;
+ Bits bits;
+ vlong off;
+
+ ARGBEGIN{
+ default:
+ usage();
+ }ARGEND
+
+ fd = 0;
+ if(argc == 1){
+ if((fd = open(*argv, OREAD)) < 0)
+ sysfatal("%r");
+ }else if(argc != 0)
+ usage();
+
+ Binit(&in, fd, OREAD);
+ Binit(&stdout, 2, OWRITE);
+ Binit(&settings, 1, OWRITE);
+ memset(&v, 0, sizeof(v));
+ memset(&bits, 0, sizeof(bits));
+ bits.b = ∈
+
+ if(Bread(&in, tmp, 6) != 6 || Bu16le(&in, &hlen) < 0)
+ sysfatal("header read failed");
+ if(memcmp(tmp, "DKIF", 4) != 0)
+ sysfatal("expected DKIF, got %02x%02x%02x%02x", tmp[0], tmp[1], tmp[2], tmp[3]);
+ if(hlen < 0x20 || Bread(&in, tmp, 4) != 4)
+ sysfatal("invalid header: hlen=%d", hlen);
+ if(Bu16le(&in, &w) < 0 || Bu16le(&in, &h) < 0 || Bu32le(&in, &tbdenum) < 0 || Bu32le(&in, &tbnum) < 0)
+ sysfatal("invalid header: %r");
+ if(Bseek(&in, hlen, 0) != hlen)
+ sysfatal("invalid IVF stream");
+
+ shgo = 0;
+ buf = malloc(1 * 1024 * 1024);
+ for(framenum = 0;; framenum++){
+ if(Bu32le(&in, &sz) < 0 || Bu64le(&in, ×tamp) < 0 || (int)sz < 0)
+ break;
+ off = Boffset(&in);
+ if(decode(&v, &bits, sz) != 0)
+ sysfatal("decode failed");
+
+ if(v.nal_unit_type == 8){ /* have sps+pps */
+ s = smprint(
+ "sps pic_height_in_map_units_minus1 %d\n"
+ "sps pic_width_in_mbs_minus1 %d\n"
+ "sps chroma_format_idc %d\n"
+ "sps frame_mbs_only_flag %d\n"
+ "sps log2_max_frame_num_minus4 %d\n"
+ "sps max_num_ref_frames %d\n"
+ "sps profile_idc %d\n"
+ "sps direct_8x8_inference_flag %d\n"
+ "sps mb_adaptive_frame_field_flag %d\n"
+ "sps seq_scaling_matrix_present_flag %d\n"
+ "sps separate_colour_plane_flag %d\n"
+ "pps chroma_qp_index_offset %d\n"
+ "pps pic_init_qp_minus26 %d\n"
+ "pps second_chroma_qp_index_offset %d\n"
+ "pps weighted_bipred_idc %d\n"
+ "pps num_ref_idx_l0_default_active_minus1 %d\n"
+ "pps num_ref_idx_l1_default_active_minus1 %d\n"
+ "pps constrained_intra_pred_flag %d\n"
+ "pps deblocking_filter_control_present_flag %d\n"
+ "pps entropy_coding_mode_flag %d\n"
+ "pps pic_scaling_matrix_present_flag %d\n"
+ "pps redundant_pic_cnt_present_flag %d\n"
+ "pps transform_8x8_mode_flag %d\n"
+ "pps weighted_pred_flag %d\n"
+ "pps pic_parameter_set_id %d\n",
+ v.sps.pic_height_in_map_units_minus1,
+ v.sps.pic_width_in_mbs_minus1,
+ v.sps.chroma_format_idc,
+ v.sps.frame_mbs_only_flag,
+ v.sps.log2_max_frame_num_minus4,
+ v.sps.max_num_ref_frames,
+ v.sps.profile_idc,
+ v.sps.direct_8x8_inference_flag,
+ v.sps.mb_adaptive_frame_field_flag,
+ v.sps.seq_scaling_matrix_present_flag,
+ v.sps.separate_colour_plane_flag,
+ v.pps.chroma_qp_index_offset,
+ v.pps.pic_init_qp_minus26,
+ v.pps.second_chroma_qp_index_offset,
+ v.pps.weighted_bipred_idc,
+ v.pps.num_ref_idx_l0_default_active_minus1,
+ v.pps.num_ref_idx_l1_default_active_minus1,
+ v.pps.constrained_intra_pred_flag,
+ v.pps.deblocking_filter_control_present_flag,
+ v.pps.entropy_coding_mode_flag,
+ v.pps.pic_scaling_matrix_present_flag,
+ v.pps.redundant_pic_cnt_present_flag,
+ v.pps.transform_8x8_mode_flag,
+ v.pps.weighted_pred_flag,
+ v.pps.pic_parameter_set_id
+ );
+ pwrite(1, s, strlen(s), 0);
+ free(s);
+ shgo = 1;
+ }else if(shgo){
+ s = smprint(
+ "nal_ref_idc %d\n"
+ "nal_unit_type %d\n"
+ "sh frame_num %d\n"
+ "sh idr_pic_id %d\n"
+ "sh size_dec_ref_pic_marking %d\n"
+ "sh size_pic_order_cnt_lsb %d\n"
+ "sh size_delta_pic_order_cnt_bottom %d\n"
+ "sh size_delta_pic_order_cnt0 %d\n"
+ "sh size_delta_pic_order_cnt1 %d\n"
+ "sh field_pic_flag %d\n"
+ "sh bottom_field_flag %d\n",
+ v.nal_ref_idc,
+ v.nal_unit_type,
+ v.sh.frame_num,
+ v.sh.idr_pic_id,
+ v.sh.size_dec_ref_pic_marking,
+ v.sh.size_pic_order_cnt_lsb,
+ v.sh.size_delta_pic_order_cnt_bottom,
+ v.sh.size_delta_pic_order_cnt0,
+ v.sh.size_delta_pic_order_cnt1,
+ v.sh.field_pic_flag,
+ v.sh.bottom_field_flag
+ );
+ pwrite(1, s, strlen(s), 0);
+ Bseek(&in, off, 0);
+ Bread(&in, buf, sz);
+ pwrite(1, buf, sz, -1);
+ }
+
+ Bseek(&in, off+sz, 0);
+ bits.nb = 0;
+ }
+
+ Bterm(&in);
+ Bterm(&stdout);
+
+ exits(nil);
+}
--- a/mkfile
+++ b/mkfile
@@ -1,6 +1,6 @@
</$objtype/mkfile
-TARG=h264 hantest cabac
+TARG=h264 hantest cabac ivfh264
BIN=/$objtype/bin
default:V: all