ref: 6d9c27e525cb86a650ff7d4fc82fc27bb74fd59c
dir: /ivfh264.c/
#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, vpu;
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
vpu = open("/dev/vpu", ORDWR);
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(
"decode h.264\n"
"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
);
if(pwrite(vpu, s, strlen(s), 0) < 0)
sysfatal("sps+pps: %r");
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
);
if(pwrite(vpu, s, strlen(s), 0) < 0)
sysfatal("sh: %r");
Bseek(&in, off, 0);
Bread(&in, buf, sz);
if(pwrite(vpu, buf, sz, 1) < 0)
sysfatal("data: %r");
if(pread(vpu, buf, 0, 0) < 0){
sleep(1000);
sysfatal("read: %r");
}
sleep(1000);
}
Bseek(&in, off+sz, 0);
bits.nb = 0;
}
Bterm(&in);
Bterm(&stdout);
exits(nil);
}