static void test_mpeg(void *bytes, uint32_t len, struct h262_picparm *picparm, struct h262_seqparm *seqparm) { #if 1 struct bitstream *str = vs_new_decode(VS_H262, bytes, len); int nslice = 0; while (str->bytepos < str->bytesnum) { unsigned start_code; if (vs_start(str, &start_code)) goto err; if (start_code >= H262_START_CODE_SLICE_BASE && start_code <= H262_START_CODE_SLICE_LAST) { struct h262_slice *slice; nslice++; slice = calloc (sizeof *slice, 1); slice->mbs = calloc (sizeof *slice->mbs, picparm->pic_size_in_mbs); slice->slice_vertical_position = start_code - H262_START_CODE_SLICE_BASE; if (seqparm->vertical_size > 2800) { uint32_t svp_ext; if (vs_u(str, &svp_ext, 3)) { h262_del_slice(slice); goto err; } if (slice->slice_vertical_position >= 0x80) { fprintf(stderr, "Invalid slice start code for large picture\n"); goto err; } slice->slice_vertical_position += svp_ext * 0x80; } if (slice->slice_vertical_position >= picparm->pic_height_in_mbs) { fprintf(stderr, "slice_vertical_position too large\n"); goto err; } if (h262_slice(str, seqparm, picparm, slice)) { // h262_print_slice(seqparm, picparm, slice); h262_del_slice(slice); goto err; } // h262_print_slice(seqparm, picparm, slice); if (vs_end(str)) { h262_del_slice(slice); goto err; } h262_del_slice(slice); } else { fprintf(stderr, "Unknown start code %08x\n", start_code); goto err; } } return; err: assert(0); exit(1); #endif }
int vs_ue(struct bitstream *str, uint32_t *val) { int lzb = 0; uint32_t tmp; if (str->dir == VS_ENCODE) { tmp = 0; if (*val >= (uint32_t)0xffffffff) { fprintf (stderr, "Exp-Golomb number larger than 2^32-2\n"); return 1; } while (*val >= (uint32_t)(1u << (lzb + 1)) - 1) { if (vs_u(str, &tmp, 1)) return 1; lzb++; } tmp = 1; if (vs_u(str, &tmp, 1)) return 1; tmp = *val - ((1 << lzb) - 1); if (vs_u(str, &tmp, lzb)) return 1; return 0; } else { do { if (vs_u(str, &tmp, 1)) return 1; lzb++; } while (!tmp); lzb--; if (lzb > 31) { fprintf (stderr, "Exp-Golomb number larger than 2^32-2\n"); return 1; } if (vs_u(str, &tmp, lzb)) return 1; *val = tmp + (1u << lzb) - 1; return 0; } }
int main() { uint8_t *bytes = 0; int bytesnum = 0; int bytesmax = 0; int c; int res; while ((c = getchar()) != EOF) { ADDARRAY(bytes, c); } struct bitstream *str = vs_new_decode(VS_H262, bytes, bytesnum); struct h262_seqparm *seqparm = calloc(sizeof *seqparm, 1); struct h262_picparm *picparm = calloc(sizeof *picparm, 1); struct h262_gop *gop = calloc(sizeof *gop, 1); struct h262_slice *slice; while (1) { uint32_t start_code; uint32_t ext_start_code; if (vs_start(str, &start_code)) goto err; printf("Start code: %02x\n", start_code); switch (start_code) { case H262_START_CODE_SEQPARM: if (h262_seqparm(str, seqparm)) goto err; if (vs_end(str)) goto err; h262_print_seqparm(seqparm); break; case H262_START_CODE_PICPARM: if (h262_picparm(str, seqparm, picparm)) goto err; if (vs_end(str)) goto err; h262_print_picparm(picparm); break; case H262_START_CODE_GOP: if (h262_gop(str, gop)) goto err; if (vs_end(str)) goto err; h262_print_gop(gop); break; case H262_START_CODE_EXTENSION: if (vs_u(str, &ext_start_code, 4)) goto err; printf("Extension start code: %d\n", ext_start_code); switch (ext_start_code) { case H262_EXT_SEQUENCE: if (h262_seqparm_ext(str, seqparm)) goto err; if (vs_end(str)) goto err; h262_print_seqparm(seqparm); break; case H262_EXT_PIC_CODING: if (h262_picparm_ext(str, seqparm, picparm)) goto err; if (vs_end(str)) goto err; h262_print_picparm(picparm); break; default: fprintf(stderr, "Unknown extension start code\n"); goto err; } break; case H262_START_CODE_END: printf ("End of sequence.\n"); break; default: if (start_code >= H262_START_CODE_SLICE_BASE && start_code <= H262_START_CODE_SLICE_LAST) { slice = calloc (sizeof *slice, 1); slice->mbs = calloc (sizeof *slice->mbs, picparm->pic_size_in_mbs); slice->slice_vertical_position = start_code - H262_START_CODE_SLICE_BASE; if (seqparm->vertical_size > 2800) { uint32_t svp_ext; if (vs_u(str, &svp_ext, 3)) { h262_del_slice(slice); goto err; } if (slice->slice_vertical_position >= 0x80) { fprintf(stderr, "Invalid slice start code for large picture\n"); goto err; } slice->slice_vertical_position += svp_ext * 0x80; } if (slice->slice_vertical_position >= picparm->pic_height_in_mbs) { fprintf(stderr, "slice_vertical_position too large\n"); goto err; } if (h262_slice(str, seqparm, picparm, slice)) { h262_print_slice(seqparm, picparm, slice); h262_del_slice(slice); goto err; } h262_print_slice(seqparm, picparm, slice); if (vs_end(str)) { h262_del_slice(slice); goto err; } h262_del_slice(slice); break; } else { fprintf(stderr, "Unknown start code\n"); goto err; } } printf("NAL decoded successfully\n\n"); continue; err: res = vs_search_start(str); if (res == -1) return 1; if (!res) break; printf("\n"); } return 0; }
int h262_seqparm(struct bitstream *str, struct h262_seqparm *seqparm) { uint32_t hs = seqparm->horizontal_size & 0xfff; uint32_t vs = seqparm->vertical_size & 0xfff; uint32_t br = seqparm->bit_rate & 0x3ffff; uint32_t vbv = seqparm->vbv_buffer_size & 0x3ff; int i; if (str->dir == VS_ENCODE && !seqparm->is_ext) { if (hs != seqparm->horizontal_size) { fprintf(stderr, "horizontal_size too big for MPEG1\n"); return 1; } if (vs != seqparm->vertical_size) { fprintf(stderr, "vertical_size too big for MPEG1\n"); return 1; } if (br != seqparm->bit_rate) { fprintf(stderr, "bit_rate too big for MPEG1\n"); return 1; } if (vbv != seqparm->vbv_buffer_size) { fprintf(stderr, "vbv_buffer_size too big for MPEG1\n"); return 1; } } if (vs_u(str, &hs, 12)) return 1; if (vs_u(str, &vs, 12)) return 1; if (vs_u(str, &seqparm->aspect_ratio_information, 4)) return 1; if (vs_u(str, &seqparm->frame_rate_code, 4)) return 1; if (vs_u(str, &br, 18)) return 1; if (vs_mark(str, 1, 1)) return 1; if (vs_u(str, &vbv, 10)) return 1; if (vs_u(str, &seqparm->constrained_parameters_flag, 1)) return 1; if (vs_u(str, &seqparm->load_intra_quantiser_matrix, 1)) return 1; if (seqparm->load_intra_quantiser_matrix) { for (i = 0; i < 64; i++) if (vs_u(str, &seqparm->intra_quantiser_matrix[i], 8)) return 1; } if (vs_u(str, &seqparm->load_non_intra_quantiser_matrix, 1)) return 1; if (seqparm->load_non_intra_quantiser_matrix) { for (i = 0; i < 64; i++) if (vs_u(str, &seqparm->non_intra_quantiser_matrix[i], 8)) return 1; } if (str->dir == VS_DECODE) { seqparm->horizontal_size = hs; seqparm->vertical_size = vs; seqparm->bit_rate = br; seqparm->vbv_buffer_size = vbv; seqparm->is_ext = 0; seqparm->has_disp_ext = 0; } if (!seqparm->is_ext) { if (vs_infer(str, &seqparm->progressive_sequence, 1)) return 1; if (vs_infer(str, &seqparm->chroma_format, 1)) return 1; if (vs_infer(str, &seqparm->low_delay, 0)) return 1; if (vs_infer(str, &seqparm->low_delay, 0)) return 1; if (vs_infer(str, &seqparm->frame_rate_extension_n, 0)) return 1; if (vs_infer(str, &seqparm->frame_rate_extension_d, 0)) return 1; } return 0; }