//--------------------------------------------------------------------------------------------- int32_t BitMessage::read_uint8() const { return (int32_t)read_bits(8); }
/*! * \param *dc The current DecodingContext. * \param mbAddr The current macroblock address. * \return 0 if macroblock decoding fail, 1 otherwise. * * This function extract one macroblock from the bitstream, handle intra/inter * prediction for its blocks. */ int macroblock_layer(DecodingContext_t *dc, const int mbAddr) { TRACE_INFO(MB, "<> " BLD_GREEN "macroblock_layer(" CLR_RESET "%i" BLD_GREEN ")\n" CLR_RESET, mbAddr); int retcode = FAILURE; // Macroblock allocation //////////////////////////////////////////////////////////////////////////// dc->mb_array[mbAddr] = (Macroblock_t*)calloc(1, sizeof(Macroblock_t)); if (dc->mb_array[mbAddr] == NULL) { TRACE_ERROR(MB, "Unable to alloc new macroblock!\n"); } else { // Set macroblock address dc->mb_array[mbAddr]->mbAddr = mbAddr; // Shortcuts pps_t *pps = dc->pps_array[dc->active_slice->pic_parameter_set_id]; sps_t *sps = dc->sps_array[pps->seq_parameter_set_id]; slice_t *slice = dc->active_slice; Macroblock_t *mb = dc->mb_array[mbAddr]; // Macroblock decoding //////////////////////////////////////////////////////////////////////// #if ENABLE_DEBUG mb->mbFileAddrStart = bitstream_get_absolute_bit_offset(dc->bitstr); #endif // ENABLE_DEBUG deriv_macroblockneighbours_availability(dc, mbAddr); MbPosition(mb, sps); if (pps->entropy_coding_mode_flag) mb->mb_type = read_ae(dc, SE_mb_type); else mb->mb_type = read_ue(dc->bitstr); mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0); mb->NumMbPart = NumMbPart(slice->slice_type, mb->mb_type); if (mb->mb_type == I_PCM) { #if ENABLE_IPCM TRACE_3(MB, "---- macroblock_layer - I PCM macroblock\n"); while (bitstream_check_alignment(dc->bitstr) == false) { if (read_bit(dc->bitstr) != 0) // pcm_alignment_zero_bit { TRACE_ERROR(MB, " Error while reading pcm_alignment_zero_bit: must be 0!\n"); return FAILURE; } } // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2 initCabacDecodingEngine(dc); int i = 0; for (i = 0; i < 256; i++) { mb->pcm_sample_luma[i] = (uint8_t)read_bits(dc->bitstr, sps->BitDepthY); } // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2 initCabacDecodingEngine(dc); for (i = 0; i < 2 * sps->MbWidthC * sps->MbHeightC; i++) { mb->pcm_sample_chroma[i] = (uint8_t)read_bits(dc->bitstr, sps->BitDepthC); } // CABAC initialization process //FIXME needed? See 'ITU-T H.264' recommendation 9.3.1.2 initCabacDecodingEngine(dc); #else // ENABLE_IPCM TRACE_ERROR(MB, "I_PCM decoding is currently disabled!\n"); return UNSUPPORTED; #endif // ENABLE_IPCM } else { #if ENABLE_INTER_PRED bool noSubMbPartSizeLessThan8x8Flag = true; if (mb->mb_type != I_NxN && mb->MbPartPredMode[0] != Intra_16x16 && mb->NumMbPart == 4) { TRACE_3(MB, "---- macroblock_layer - mb partition & related\n"); int mbPartIdx = 0; for (mbPartIdx = 0; mbPartIdx < 4; mbPartIdx++) { if (mb->sub_mb_type[mbPartIdx] != B_Direct_8x8) { if (NumSubMbPart(slice->slice_type, mb->sub_mb_type[mbPartIdx]) > 1) { noSubMbPartSizeLessThan8x8Flag = false; } } else if (sps->direct_8x8_inference_flag == false) { noSubMbPartSizeLessThan8x8Flag = false; } } // Read sub macroblock prediction mode sub_mb_pred(dc, mb->mb_type, mb->sub_mb_type); } else #endif // ENABLE_INTER_PRED { TRACE_3(MB, "---- macroblock_layer - transform_size_8x8_flag & prediction modes\n"); if (pps->transform_8x8_mode_flag == true && mb->mb_type == I_NxN) { if (pps->entropy_coding_mode_flag) mb->transform_size_8x8_flag = read_ae(dc, SE_transform_size_8x8_flag); else mb->transform_size_8x8_flag = read_bit(dc->bitstr); // Need to update MbPartPredMode in order to detect I_8x8 prediction mode mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0); } // Read macroblock prediction mode mb_pred(dc, mb); } if (mb->MbPartPredMode[0] != Intra_16x16) { TRACE_3(MB, "---- macroblock_layer - coded block pattern & transform_size_8x8_flag\n"); if (pps->entropy_coding_mode_flag) mb->coded_block_pattern = read_ae(dc, SE_coded_block_pattern); else mb->coded_block_pattern = read_me(dc->bitstr, sps->ChromaArrayType, dc->IdrPicFlag); mb->CodedBlockPatternLuma = mb->coded_block_pattern % 16; mb->CodedBlockPatternChroma = mb->coded_block_pattern / 16; #if ENABLE_INTER_PRED if (mb->CodedBlockPatternLuma > 0 && pps->transform_8x8_mode_flag == true && mb->mb_type != I_NxN && noSubMbPartSizeLessThan8x8Flag == true && (mb->mb_type != B_Direct_16x16 || sps->direct_8x8_inference_flag == true)) { if (pps->entropy_coding_mode_flag) mb->transform_size_8x8_flag = read_ae(dc, SE_transform_size_8x8_flag); else mb->transform_size_8x8_flag = read_bit(dc->bitstr); // Need to update MbPartPredMode in order to account for I_8x8 prediction mode if (transform_size_8x8_flag) mb->MbPartPredMode[0] = MbPartPredMode(mb, slice->slice_type, 0); } #endif // ENABLE_INTER_PRED } if (mb->CodedBlockPatternLuma > 0 || mb->CodedBlockPatternChroma > 0 || mb->MbPartPredMode[0] == Intra_16x16) { TRACE_3(MB, "---- macroblock_layer - quantization parameter & residual datas\n"); // Read QP delta if (pps->entropy_coding_mode_flag) mb->mb_qp_delta = read_ae(dc, SE_mb_qp_delta); else mb->mb_qp_delta = read_se(dc->bitstr); // Parse the residual coefficients //////////////////////////////////////////////////////////////// // Luma levels residual_luma(dc, 0, 15); // Chroma levels residual_chroma(dc, 0, 15); } else { TRACE_3(MB, "---- macroblock_layer - No residual datas to decode in this macroblock\n"); } // Compute luma Quantization Parameters if (mb->mb_qp_delta) mb->QPY = ((slice->QPYprev + mb->mb_qp_delta + 52 + sps->QpBdOffsetY*2) % (52 + sps->QpBdOffsetY)) - sps->QpBdOffsetY; else mb->QPY = slice->QPYprev; mb->QPprimeY = mb->QPY + sps->QpBdOffsetY; slice->QPYprev = mb->QPY; // Set Transform Bypass Mode if (sps->qpprime_y_zero_transform_bypass_flag == true && mb->QPprimeY == 0) mb->TransformBypassModeFlag = true; // Prediction process (include quantization and transformation stages) //////////////////////////////////////////////////////////////// if (dc->IdrPicFlag) { retcode = intra_prediction_process(dc, mb); } else { retcode = inter_prediction_process(dc, mb); } // Print macroblock(s) header and block data ? //////////////////////////////////////////////////////////////// #if ENABLE_DEBUG mb->mbFileAddrStop = bitstream_get_absolute_bit_offset(dc->bitstr) - 1; int frame_debug_range[2] = {-1, -1}; // Range of (idr) frame(s) to debug/analyse int mb_debug_range[2] = {-1, -1}; // Range of macroblock(s) to debug/analyse if (dc->idrCounter >= frame_debug_range[0] && dc->idrCounter <= frame_debug_range[1]) { if (mb->mbAddr >= mb_debug_range[0] && mb->mbAddr <= mb_debug_range[1]) { print_macroblock_layer(dc, mb); print_macroblock_pixel_residual(mb); print_macroblock_pixel_predicted(mb); print_macroblock_pixel_final(mb); } } #endif // ENABLE_DEBUG } TRACE_3(MB, "---- macroblock_layer - the end\n\n"); } return retcode; }
int itsex_decompress8(HIO_HANDLE *src, uint8 *dst, int len, int it215) { uint32 size = 0; uint32 block_count = 0; uint32 bitbuf = 0; int bitnum = 0; uint8 left = 0, temp = 0, temp2 = 0; uint32 d, pos; while (len) { if (!block_count) { block_count = 0x8000; size = hio_read16l(src); left = 9; temp = temp2 = 0; bitbuf = bitnum = 0; } d = block_count; if (d > len) d = len; /* Unpacking */ pos = 0; do { uint16 bits = read_bits(src, &bitbuf, &bitnum, left); if (hio_eof(src)) return -1; if (left < 7) { uint32 i = 1 << (left - 1); uint32 j = bits & 0xffff; if (i != j) goto unpack_byte; bits = (read_bits(src, &bitbuf, &bitnum, 3) + 1) & 0xff; if (hio_eof(src)) return -1; left = ((uint8)bits < left) ? (uint8)bits : (uint8)((bits + 1) & 0xff); goto next; } if (left < 9) { uint16 i = (0xff >> (9 - left)) + 4; uint16 j = i - 8; if ((bits <= j) || (bits > i)) goto unpack_byte; bits -= j; left = ((uint8)(bits & 0xff) < left) ? (uint8)(bits & 0xff) : (uint8)((bits + 1) & 0xff); goto next; } if (left >= 10) goto skip_byte; if (bits >= 256) { left = (uint8) (bits + 1) & 0xff; goto next; } unpack_byte: if (left < 8) { uint8 shift = 8 - left; signed char c = (signed char)(bits << shift); c >>= shift; bits = (uint16) c; } bits += temp; temp = (uint8)bits; temp2 += temp; dst[pos] = it215 ? temp2 : temp; skip_byte: pos++; next: /* if (slen <= 0) return -1 */; } while (pos < d);
/*! * \brief Parse a program stream directory structure. * \param *bitstr A bitstream. * \param *packet A program stream directory structure. * \return retcode 1 if succeed, 0 otherwise. * * H.222 / 2.5.5 Program Stream directory. */ static int parse_program_stream_directory(Bitstream_t *bitstr, ProgramStreamDirectory_t *packet) { TRACE_INFO(MPS, BLD_GREEN "parse_program_stream_directory()" CLR_RESET " @ %i\n", bitstream_get_absolute_byte_offset(bitstr) - 4); int retcode = SUCCESS; int i = 0; packet->packet_start_code_prefix = 0x000001; packet->directory_stream_id = 0xFF; packet->PES_packet_length = read_bits(bitstr, 16); packet->number_of_access_units = read_bits(bitstr, 15); MARKER_BIT packet->prev_directory_offset = read_bits(bitstr, 15) << 30; MARKER_BIT packet->prev_directory_offset += read_bits(bitstr, 15) << 15; MARKER_BIT packet->prev_directory_offset += read_bits(bitstr, 15); MARKER_BIT packet->next_directory_offset = read_bits(bitstr, 15) << 30; MARKER_BIT packet->next_directory_offset += read_bits(bitstr, 15) << 15; MARKER_BIT packet->next_directory_offset += read_bits(bitstr, 15); MARKER_BIT for (i = 0; i < packet->number_of_access_units; i++) { // TODO stack it? packet->packet_stream_id = read_bits(bitstr, 8); packet->PES_header_position_offset_sign = read_bit(bitstr); packet->PES_header_position_offset = read_bits(bitstr, 14) << 30; MARKER_BIT packet->PES_header_position_offset += read_bits(bitstr, 15) << 15; MARKER_BIT packet->PES_header_position_offset += read_bits(bitstr, 15); MARKER_BIT packet->reference_offset = read_bits(bitstr, 16); MARKER_BIT int reserved1 = read_bits(bitstr, 3); packet->PTS = read_bits(bitstr, 3) << 30; MARKER_BIT packet->PTS += read_bits(bitstr, 15) << 15; MARKER_BIT packet->PTS += read_bits(bitstr, 15); MARKER_BIT packet->byes_to_read = read_bits(bitstr, 15) << 15; MARKER_BIT packet->byes_to_read += read_bits(bitstr, 8); MARKER_BIT packet->intra_coded_indicator = read_bit(bitstr); packet->coding_parameters_indicator = read_bits(bitstr, 2); int reserved2 = read_bits(bitstr, 4); } return retcode; }
/*! * \brief Parse a pack header structure. * \param *bitstr The bitstream to use. * \param *pack_header A pointer to a pack_header structure. * \param *system_header A pointer to a system_header structure. * \return retcode 1 if succeed, 0 otherwise. * * This parser is based on the 'ISO/IEC 13818-1' international standard, part 1: * 'Transmission multiplexing and synchronization'. */ static int parse_pack_header(Bitstream_t *bitstr, PackHeader_t *pack_header, SystemHeader_t *system_header) { TRACE_INFO(MPS, BLD_GREEN "parse_pack_header()" CLR_RESET " @ %i\n", bitstream_get_absolute_byte_offset(bitstr) - 4); int retcode = SUCCESS; int i = 0; pack_header->pack_start_code = PES_PACK_HEADER; if (read_bits(bitstr, 2) != 1) { TRACE_ERROR(MPS, "wrong 'marker_bit'\n"); return FAILURE; } pack_header->system_clock_reference_base = read_bits(bitstr, 3) << 30; MARKER_BIT pack_header->system_clock_reference_base += read_bits(bitstr, 15) << 15; MARKER_BIT pack_header->system_clock_reference_base += read_bits(bitstr, 15); MARKER_BIT pack_header->system_clock_reference_extension = read_bits(bitstr, 9); MARKER_BIT pack_header->program_mux_rate = read_bits(bitstr, 22); MARKER_BIT MARKER_BIT int reserved = read_bits(bitstr, 5); pack_header->pack_stuffing_length = read_bits(bitstr, 3); // Stuffing for (i = 0; i < pack_header->pack_stuffing_length; i++) { if (read_bits(bitstr, 8) != 0xFF) { TRACE_ERROR(MPS, "Wrong 'stuffing_byte'\n"); return FAILURE; } } // System header if (next_bits(bitstr, 32) == PES_SYSTEM_HEADER) { TRACE_INFO(MPS, BLD_GREEN "parse_system_header()" CLR_RESET " @ %i\n", bitstream_get_absolute_byte_offset(bitstr) - 4); skip_bits(bitstr, 32); system_header->header_length = read_bits(bitstr, 16); MARKER_BIT system_header->rate_bound = read_bits(bitstr, 22); MARKER_BIT system_header->audio_bound = read_bits(bitstr, 6); system_header->fixed_flag = read_bits(bitstr, 1); system_header->CSPS_flag = read_bits(bitstr, 1); system_header->system_audio_lock_flag = read_bits(bitstr, 1); system_header->system_video_lock_flag = read_bits(bitstr, 1); MARKER_BIT system_header->video_bound = read_bits(bitstr, 5); system_header->packet_rate_restriction_flag = read_bits(bitstr, 1); int reserved_bits = read_bits(bitstr, 7); // stack it? while (next_bit(bitstr) == 1) { system_header->stream_id = read_bits(bitstr, 8); MARKER_BIT MARKER_BIT system_header->PSTD_buffer_bound_scale = read_bits(bitstr, 1); system_header->PSTD_buffer_size_bound = read_bits(bitstr, 13); } } else { TRACE_2(MPS, " > No system_header()\n"); } return retcode; }
// Return TRUE if the data parsing finished, FALSE otherwise. // estream->pos is advanced. Data is only processed if esstream->error // is FALSE, parsing can set esstream->error to TRUE. static int gop_header(struct lib_ccx_ctx *ctx, struct bitstream *esstream, struct cc_subtitle *sub) { dbg_print(CCX_DMT_VERBOSE, "GOP header\n"); if (esstream->error || esstream->bitsleft <= 0) return 0; // We only get here after seeing that start code if (read_u32(esstream) != 0xB8010000) // LSB first (0x000001B8) fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!"); unsigned drop_frame_flag = (unsigned) read_bits(esstream,1); struct gop_time_code gtc; gtc.time_code_hours = (int) read_bits(esstream,5); gtc.time_code_minutes = (int) read_bits(esstream,6); skip_bits(esstream,1); // Marker bit gtc.time_code_seconds = (int) read_bits(esstream,6); gtc.time_code_pictures = (int) read_bits(esstream,6); gtc.inited = 1; calculate_ms_gop_time(>c); if (esstream->bitsleft < 0) return 0; if (gop_accepted(>c)) { // Do GOP padding during GOP header. The previous GOP and all // included captions are written. Use the current GOP time to // do the padding. // Flush buffered cc blocks before doing the housekeeping if (has_ccdata_buffered) { process_hdcc(ctx, sub); } // Last GOPs pulldown frames if ((current_pulldownfields>0) != (pulldownfields>0)) { current_pulldownfields = pulldownfields; dbg_print(CCX_DMT_VERBOSE, "Pulldown: %s", (pulldownfields ? "on" : "off")); if (pulldownfields) dbg_print(CCX_DMT_VERBOSE, " - %u fields in last GOP", pulldownfields); dbg_print(CCX_DMT_VERBOSE, "\n"); } pulldownfields = 0; // Report synchronization jumps between GOPs. Warn if there // are 20% or more deviation. if ( (ccx_options.debug_mask & CCX_DMT_TIME) && ((gtc.ms - gop_time.ms // more than 20% longer > ctx->frames_since_last_gop*1000.0/current_fps*1.2) || (gtc.ms - gop_time.ms // or 20% shorter < ctx->frames_since_last_gop*1000.0/current_fps*0.8)) && first_gop_time.inited ) { mprint("\rWarning: Jump in GOP timing.\n"); mprint(" (old) %s", print_mstime(gop_time.ms)); mprint(" + %s (%uF)", print_mstime((LLONG) (ctx->frames_since_last_gop *1000.0/current_fps)), ctx->frames_since_last_gop); mprint(" != (new) %s\n", print_mstime(gtc.ms)); } if (first_gop_time.inited == 0) { first_gop_time = gtc; // It needs to be "+1" because the frame count starts at 0 and we // need the length of all frames. if ( total_frames_count == 0 ) { // If this is the first frame there cannot be an offset fts_fc_offset = 0; // first_gop_time.ms stays unchanged } else { fts_fc_offset = (LLONG) ((total_frames_count+1) *1000.0/current_fps); // Compensate for those written before first_gop_time.ms -= fts_fc_offset; } dbg_print(CCX_DMT_TIME, "\nFirst GOP time: %02u:%02u:%02u:%03u %+lldms\n", gtc.time_code_hours, gtc.time_code_minutes, gtc.time_code_seconds, (unsigned) (1000.0*gtc.time_code_pictures/current_fps), fts_fc_offset); } gop_time = gtc; ctx->frames_since_last_gop=0; // Indicate that we read a gop header (since last frame number 0) ctx->saw_gop_header = 1; // If we use GOP timing, reconstruct the PTS from the GOP if (ccx_options.use_gop_as_pts==1) { current_pts = gtc.ms*(MPEG_CLOCK_FREQ/1000); if (pts_set==0) pts_set=1; current_tref = 0; frames_since_ref_time = 0; set_fts(); fts_at_gop_start = get_fts_max(); } else { // FIXME: Wrong when PTS are not increasing but are identical // troughout the GOP and then jump to the next time for the // next GOP. // This effect will also lead to captions being one GOP early // for DVD captions. fts_at_gop_start = get_fts_max() + (LLONG) (1000.0/current_fps); } if (ccx_options.debug_mask & CCX_DMT_TIME) { dbg_print(CCX_DMT_TIME, "\nNew GOP:\n"); dbg_print(CCX_DMT_TIME, "\nDrop frame flag: %u:\n", drop_frame_flag); print_debug_timing(); } } return 1; }
void H264_decodePPS(int v, u_char *b, int len) { H264_PPS pps = {0,}; uint8_t nal_unit_type = b[3]&0x1F; bitdata data = {0,}; data.data = (byte*)(b+4); data.data_len = remove_0x03(b+4, len-4); data.cur_bit = -1; read_exp_golomb(&data, &pps.pic_parameter_set_id); read_exp_golomb(&data, &pps.seq_parameter_set_id); read_bit(&data, &pps.entropy_coding_mode_flag); read_bit(&data, &pps.pic_order_present_flag); read_exp_golomb(&data, &pps.num_slice_groups_minus1); if (pps.num_slice_groups_minus1 > 0) { read_exp_golomb(&data, &pps.slice_group_map_type); switch (pps.slice_group_map_type) { case 0: { uint32_t i; for (i = 0; i <= pps.num_slice_groups_minus1; ++i) { uint32_t run_length_minus1; read_exp_golomb(&data, &run_length_minus1); } } break; case 2: { uint32_t i; for (i = 0; i < pps.num_slice_groups_minus1; ++i) { uint32_t top_left, bottom_right; read_exp_golomb(&data, &top_left); read_exp_golomb(&data, &bottom_right); } } break; case 3: case 4: case 5: { read_bit(&data, &pps.slice_group_change_direction_flag); read_exp_golomb(&data, &pps.slice_group_change_rate_minus1); } break; case 6: { uint32_t i, size = (uint32_t)ceil(log2(pps.num_slice_groups_minus1+1)); read_exp_golomb(&data, &pps.pic_size_in_map_units_minus1); for (i = 0; i <= pps.pic_size_in_map_units_minus1; ++i) { uint32_t slice_group_id; read_bits(&data, size, &slice_group_id); } } break; } // switch (pps.slice_group_map_type) } // if (pps.num_slice_groups_minus1 > 0) read_exp_golomb(&data, &pps.num_ref_idx_l0_active_minus1); read_exp_golomb(&data, &pps.num_ref_idx_l1_active_minus1); read_bit(&data, &pps.weighted_pred_flag); read_bits(&data, 2, &pps.weighted_bipred_idc); read_signed_exp_golomb(&data, &pps.pic_init_qp_minus26); read_signed_exp_golomb(&data, &pps.pic_init_qs_minus26); read_signed_exp_golomb(&data, &pps.chroma_qp_index_offset); read_bit(&data, &pps.deblocking_filter_control_present_flag); read_bit(&data, &pps.constrained_intra_pred_flag); read_bit(&data, &pps.redundant_pic_cnt_present_flag); decoder.pps = pps; out_SB_NL(v, "pic_parameter_set_id: ", pps.pic_parameter_set_id); out_SB_NL(v, "seq_parameter_set_id: ", pps.seq_parameter_set_id); out_SB_NL(v, "entropy_coding_mode_flag: ", pps.entropy_coding_mode_flag); out_SB_NL(v, "pic_order_present_flag: ", pps.pic_order_present_flag); out_SB_NL(v, "num_slice_groups_minus1: ", pps.num_slice_groups_minus1); if (pps.num_slice_groups_minus1 > 0) { out_SB_NL(v, "slice_group_map_type: ", pps.slice_group_map_type); switch (pps.slice_group_map_type) { case 3: case 4: case 5: out_SB_NL(v, "slice_group_change_direction_flag: ", pps.slice_group_change_direction_flag); out_SB_NL(v, "slice_group_change_rate_minus1: ", pps.slice_group_change_rate_minus1); break; case 6: out_SB_NL(v, "pic_size_in_map_units_minus1: ", pps.pic_size_in_map_units_minus1); break; } } out_SB_NL(v, "num_ref_idx_l0_active_minus1: ", pps.num_ref_idx_l0_active_minus1); out_SB_NL(v, "num_ref_idx_l1_active_minus1: ", pps.num_ref_idx_l1_active_minus1); out_SB_NL(v, "weighted_pred_flag: ", pps.weighted_pred_flag); out_SB_NL(v, "weighted_bipred_idc: ", pps.weighted_bipred_idc); out_SLL_NL(v, "pic_init_qp_minus26: ", pps.pic_init_qp_minus26); out_SLL_NL(v, "pic_init_qs_minus26: ", pps.pic_init_qs_minus26); out_SLL_NL(v, "chroma_qp_index_offset: ", pps.chroma_qp_index_offset); out_SB_NL(v, "deblocking_filter_control_present_flag: ", pps.deblocking_filter_control_present_flag); out_SB_NL(v, "constrained_intra_pred_flag: ", pps.constrained_intra_pred_flag); out_SB_NL(v, "redundant_pic_cnt_present_flag: ", pps.redundant_pic_cnt_present_flag); }
/*! * \param *dc The current DecodingContext. * \param *slice The current Slice. */ static int decodeSliceHeader(DecodingContext_t *dc, slice_t *slice) { TRACE_INFO(SLICE, "> " BLD_GREEN "decodeSliceHeader()\n" CLR_RESET); // Slice header decoding //////////////////////////////////////////////////////////////////////////// slice->first_mb_in_slice = read_ue(dc->bitstr); slice->slice_type = read_ue(dc->bitstr); slice->pic_parameter_set_id = read_ue(dc->bitstr); // Shortcuts pps_t *pps = dc->pps_array[slice->pic_parameter_set_id]; sps_t *sps = dc->sps_array[pps->seq_parameter_set_id]; if (sps->separate_colour_plane_flag) { slice->colour_plane_id = read_bits(dc->bitstr, 2); } slice->frame_num = read_bits(dc->bitstr, sps->log2_max_frame_num_minus4 + 4); if (sps->frame_mbs_only_flag == false) { slice->field_pic_flag = read_bit(dc->bitstr); if (slice->field_pic_flag) { slice->bottom_field_flag = read_bit(dc->bitstr); slice->MaxPicNum = sps->MaxFrameNum*2; slice->CurrPicNum = slice->frame_num*2 + 1; } else { slice->MaxPicNum = sps->MaxFrameNum; slice->CurrPicNum = slice->frame_num; } } slice->MbaffFrameFlag = sps->mb_adaptive_frame_field_flag && !slice->field_pic_flag; slice->PicHeightInMbs = sps->FrameHeightInMbs / (1 + slice->field_pic_flag); slice->PicHeightInSamplesL = slice->PicHeightInMbs * 16; slice->PicHeightInSamplesC = slice->PicHeightInMbs * sps->MbHeightC; slice->PicSizeInMbs = sps->PicWidthInMbs * slice->PicHeightInMbs; if (dc->IdrPicFlag) { slice->PrevRefFrameNum = 0; slice->idr_pic_id = read_ue(dc->bitstr); } if (sps->pic_order_cnt_type == 0) { slice->pic_order_cnt_lsb = read_bits(dc->bitstr, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); if (pps->bottom_field_pic_order_in_frame_present_flag && slice->field_pic_flag == false) { slice->delta_pic_order_cnt_bottom = read_se(dc->bitstr); } } else if (sps->pic_order_cnt_type == 1 && sps->delta_pic_order_always_zero_flag == false) { slice->delta_pic_order_cnt[0] = read_se(dc->bitstr); if (pps->bottom_field_pic_order_in_frame_present_flag && slice->field_pic_flag == false) { slice->delta_pic_order_cnt[1] = read_se(dc->bitstr); } } if (pps->redundant_pic_cnt_present_flag) { slice->redundant_pic_cnt = read_ue(dc->bitstr); } if (slice->slice_type == 1 || slice->slice_type == 6) // B frame { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (B frame)\n"); return UNSUPPORTED; slice->direct_spatial_mv_pred_flag = read_bit(dc->bitstr); } if (slice->slice_type == 0 || slice->slice_type == 5 || slice->slice_type == 3 || slice->slice_type == 8 || slice->slice_type == 1 || slice->slice_type == 6) // P, SP, B frame { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (P, SP, B frame)\n"); return UNSUPPORTED; /* slice->num_ref_idx_active_override_flag = read_bit(dc->bitstr); if (slice->num_ref_idx_active_override_flag) { slice->num_ref_idx_l0_active_minus1 = read_ue(dc->bitstr); if (slice->slice_type == 1 || slice->slice_type == 6) // B frame { slice->num_ref_idx_l1_active_minus1 = read_ue(dc->bitstr); } } */ } if (dc->active_nalu->nal_unit_type == 20) { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (unit_type == 20: MVC extension)\n"); return UNSUPPORTED; } else { // RPLM slice->rplm = decodeRPLM(dc, slice); } if ((pps->weighted_pred_flag == true && (slice->slice_type == 0 || slice->slice_type == 5 || slice->slice_type == 3 || slice->slice_type == 8)) || (pps->weighted_bipred_idc == 1 && (slice->slice_type == 1 || slice->slice_type == 6))) // P, SP, B frame { // PWT slice->pwt = decodePWT(dc, slice); } if (dc->active_nalu->nal_ref_idc != 0) { // DRPM slice->drpm = decodeDRPM(dc, slice); } if (pps->entropy_coding_mode_flag == true && ((slice->slice_type != 2 && slice->slice_type != 7) && (slice->slice_type != 4 && slice->slice_type != 9))) // Not I or SI frame { slice->cabac_init_idc = read_ue(dc->bitstr); } slice->slice_qp_delta = read_se(dc->bitstr); slice->SliceQPY = 26 + pps->pic_init_qp_minus26 + slice->slice_qp_delta; slice->QPYprev = slice->SliceQPY; // Set QPYprev value to use it in the first macroblock if (slice->slice_type == 3 || slice->slice_type == 8 || slice->slice_type == 4 || slice->slice_type == 9) // SP, SI frame { #if ENABLE_SWITCHING_SLICE if (slice->slice_type == 4 || slice->slice_type == 9) { slice->sp_for_switch_flag = read_bit(dc->bitstr); } slice->slice_qs_delta = read_se(dc->bitstr); slice->SliceQSY = 26 + pps->pic_init_qs_minus26 + slice->slice_qs_delta; #else /* ENABLE_SWITCHING_SLICE */ TRACE_ERROR(SLICE, ">>> UNSUPPORTED (slice_type == SP || slice_type == SI)\n"); return UNSUPPORTED; #endif /* ENABLE_SWITCHING_SLICE */ } if (pps->deblocking_filter_control_present_flag) { slice->disable_deblocking_filter_idc = read_ue(dc->bitstr); if (slice->disable_deblocking_filter_idc != 1) { slice->slice_alpha_c0_offset_div2 = read_se(dc->bitstr); slice->slice_beta_offset_div2 = read_se(dc->bitstr); slice->FilterOffsetA = slice->slice_alpha_c0_offset_div2 << 1; slice->FilterOffsetB = slice->slice_beta_offset_div2 << 1; } } if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 && pps->slice_group_map_type <= 5) { TRACE_ERROR(SLICE, ">>> UNSUPPORTED (FMO)\n"); return UNSUPPORTED; } // Check content return checkSliceHeader(dc); }
// Return TRUE if the data parsing finished, FALSE otherwise. // estream->pos is advanced. Data is only processed if esstream->error // is FALSE, parsing can set esstream->error to TRUE. static int sequence_header(struct lib_cc_decode *ctx, struct bitstream *esstream) { debug("Sequence header\n"); if (esstream->error || esstream->bitsleft <= 0) return 0; // We only get here after seeing that start code if (read_u32(esstream) != 0xB3010000) // LSB first (0x000001B3) fatal(CCX_COMMON_EXIT_BUG_BUG, "sequence_header: read_u32(esstream) != 0xB3010000. Please file a bug report in GitHub.\n"); unsigned hor_size = (unsigned) read_bits(esstream,12); unsigned vert_size = (unsigned) read_bits(esstream,12); unsigned aspect_ratio = (unsigned) read_bits(esstream,4); unsigned frame_rate = (unsigned) read_bits(esstream,4); #if 0 ctx->freport.width = hor_size; ctx->freport.height = vert_size; ctx->freport.aspect_ratio = aspect_ratio; ctx->freport.frame_rate = frame_rate; #endif // Discard some information read_bits(esstream, 18+1+10+1); // load_intra_quantiser_matrix if (read_bits(esstream,1)) skip_bits(esstream, 8*64); // load_non_intra_quantiser_matrix if (read_bits(esstream,1)) skip_bits(esstream, 8*64); if (esstream->bitsleft < 0) return 0; // If we got the whole sequence, process if (hor_size!= ctx->current_hor_size || vert_size!= ctx->current_vert_size || aspect_ratio!=ctx->current_aspect_ratio || frame_rate!= ctx->current_frame_rate) { // If horizontal/vertical size, framerate and/or aspect // ratio are ilegal, we discard the // whole sequence info. if (vert_size >= 288 && vert_size <= 1088 && hor_size >= 352 && hor_size <= 1920 && (hor_size*100) / vert_size >= (352*100)/576 && // The weird *100 is to avoid using floats hor_size / vert_size <= 2 && frame_rate>0 && frame_rate<9 && aspect_ratio>0 && aspect_ratio<5) { mprint ("\n\nNew video information found"); mprint ("\n"); mprint ("[%u * %u] [AR: %s] [FR: %s]", hor_size,vert_size, aspect_ratio_types[aspect_ratio], framerates_types[frame_rate]); // No newline, force the output of progressive info in picture // info part. ctx->current_progressive_sequence = 2; ctx->current_hor_size = hor_size; ctx->current_vert_size = vert_size; ctx->current_aspect_ratio = aspect_ratio; ctx->current_frame_rate=frame_rate; current_fps = framerates_values[ctx->current_frame_rate]; activity_video_info (hor_size,vert_size, aspect_ratio_types[aspect_ratio], framerates_types[frame_rate]); } else { debug("\nInvalid sequence header:\n"); debug("V: %u H: %u FR: %u AS: %u\n", vert_size, hor_size, frame_rate, aspect_ratio); esstream->error = 1; return 0; } } // Read complete return 1; }
static int read_bit(BitStreamReader *reader) { return read_bits(reader, 1); }
static int read_code_tree(LHAPM2Decoder *decoder) { uint8_t code_lengths[31]; int num_codes, min_code_length, length_bits, val; unsigned int i; // Read the number of codes in the tree. num_codes = read_bits(&decoder->bit_stream_reader, 5); // Read min_code_length, which is used as an offset. min_code_length = read_bits(&decoder->bit_stream_reader, 3); if (min_code_length < 0 || num_codes < 0) { return 0; } // Store flag variable indicating whether we want to read // the offset tree as well. decoder->need_offset_tree = num_codes >= 10 && !(num_codes == 29 && min_code_length == 0); // Minimum length of zero means a tree containing a single code. if (min_code_length == 0) { set_tree_single(decoder->code_tree, num_codes - 1); return 1; } // How many bits are used to represent each table entry? length_bits = read_bits(&decoder->bit_stream_reader, 3); if (length_bits < 0) { return 0; } // Read table of code lengths: for (i = 0; i < (unsigned int) num_codes; ++i) { // Read a table entry. A value of zero represents an // unused code. Otherwise the value represents // an offset from the minimum length (previously read). val = read_bits(&decoder->bit_stream_reader, (unsigned int) length_bits); if (val < 0) { return 0; } else if (val == 0) { code_lengths[i] = 0; } else { code_lengths[i] = (uint8_t) (min_code_length + val - 1); } } // Build the tree. build_tree(decoder->code_tree, sizeof(decoder->code_tree), code_lengths, (unsigned int) num_codes); return 1; }
//--------------------------------------------------------------------------------------------- float BitMessage::read_float() const { float value; *reinterpret_cast<int*>(&value) = read_bits(32); return value; }
//--------------------------------------------------------------------------------------------- int32_t BitMessage::read_int32() const { return (int32_t)read_bits(32); }
//--------------------------------------------------------------------------------------------- int32_t BitMessage::read_uint16() const { return (int32_t)read_bits(16); }
int h264_decode_seq_parameter_set(elementary_stream_t *st, bitstream_t *bs) { int profile_idc, level_idc, poc_type; unsigned int sps_id, tmp, i, width, height; int cbpsize = -1; h264_private_t *p; if((p = st->es_priv) == NULL) p = st->es_priv = calloc(1, sizeof(h264_private_t)); profile_idc= read_bits(bs, 8); read_bits1(bs); //constraint_set0_flag read_bits1(bs); //constraint_set1_flag read_bits1(bs); //constraint_set2_flag read_bits1(bs); //constraint_set3_flag read_bits(bs, 4); // reserved level_idc= read_bits(bs, 8); sps_id= read_golomb_ue(bs); i = 0; while(h264_lev2cpbsize[i][0] != -1) { if(h264_lev2cpbsize[i][0] >= level_idc) { cbpsize = h264_lev2cpbsize[i][1]; break; } i++; } if(cbpsize < 0) return -1; p->sps[sps_id].cbpsize = cbpsize * 125; /* Convert from kbit to bytes */ if(profile_idc >= 100){ //high profile if(read_golomb_ue(bs) == 3) //chroma_format_idc read_bits1(bs); //residual_color_transform_flag read_golomb_ue(bs); //bit_depth_luma_minus8 read_golomb_ue(bs); //bit_depth_chroma_minus8 read_bits1(bs); if(read_bits1(bs)) { /* Scaling matrices */ decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 64); decode_scaling_list(bs, 64); } } p->sps[sps_id].max_frame_num_bits = read_golomb_ue(bs) + 4; poc_type= read_golomb_ue(bs); if(poc_type == 0){ //FIXME #define read_golomb_ue(bs); } else if(poc_type == 1){//FIXME #define read_bits1(bs); read_golomb_se(bs); read_golomb_se(bs); tmp = read_golomb_ue(bs); /* poc_cycle_length */ for(i = 0; i < tmp; i++) read_golomb_se(bs); }else if(poc_type != 2){ /* Illegal poc */ return -1; } tmp = read_golomb_ue(bs); read_bits1(bs); width = read_golomb_ue(bs) + 1; /* mb width */ height = read_golomb_ue(bs) + 1; /* mb height */ p->sps[sps_id].width = width * 16; p->sps[sps_id].height = height * 16; p->sps[sps_id].mbs_only_flag = read_bits1(bs); if(!p->sps[sps_id].mbs_only_flag) p->sps[sps_id].aff = read_bits1(bs); read_bits1(bs); /* CROP */ if(read_bits1(bs)){ tmp = read_golomb_ue(bs); tmp = read_golomb_ue(bs); tmp = read_golomb_ue(bs); tmp = read_golomb_ue(bs); } if(read_bits1(bs)) { decode_vui(p, bs, sps_id); return 0; } else { return -1; } }
char * exo_decrunch(const char *in, char *out) { unsigned short int index; unsigned short int length; unsigned short int offset; char c; char literal; bit_buffer = *--in; init_table(&in); for(;;) { literal = read_bits(&in, 1); if(literal == 1) { /* literal byte */ length = 1; goto copy; } index = 0; while(read_bits(&in, 1) == 0) { ++index; } if(index == 16) { break; } if(index == 17) { literal = 1; length = read_bits(&in, 16); goto copy; } length = base[index] + read_bits(&in, bits[index]); switch(length) { case 1: index = 48 + read_bits(&in, 2); break; case 2: index = 32 + read_bits(&in, 4); break; default: index = 16 + read_bits(&in, 4); break; } offset = base[index] + read_bits(&in, bits[index]); copy: do { --out; if(literal) { c = *--in; } else { c = out[offset]; } *out = c; } while(--length > 0); } return out; }
// Return TRUE if the data parsing finished, FALSE otherwise. // estream->pos is advanced. Data is only processed if esstream->error // is FALSE, parsing can set esstream->error to TRUE. static int sequence_header(struct lib_ccx_ctx *ctx, struct bitstream *esstream) { dbg_print(CCX_DMT_VERBOSE, "Sequence header\n"); if (esstream->error || esstream->bitsleft <= 0) return 0; // We only get here after seeing that start code if (read_u32(esstream) != 0xB3010000) // LSB first (0x000001B3) fatal(CCX_COMMON_EXIT_BUG_BUG, "Impossible!"); unsigned hor_size = (unsigned) read_bits(esstream,12); unsigned vert_size = (unsigned) read_bits(esstream,12); unsigned aspect_ratio = (unsigned) read_bits(esstream,4); unsigned frame_rate = (unsigned) read_bits(esstream,4); ctx->freport.width = hor_size; ctx->freport.height = vert_size; ctx->freport.aspect_ratio = aspect_ratio; ctx->freport.frame_rate = frame_rate; // Discard some information read_bits(esstream, 18+1+10+1); // load_intra_quantiser_matrix if (read_bits(esstream,1)) skip_bits(esstream, 8*64); // load_non_intra_quantiser_matrix if (read_bits(esstream,1)) skip_bits(esstream, 8*64); if (esstream->bitsleft < 0) return 0; // If we got the whole sequence, process if (hor_size!=current_hor_size || vert_size!=current_vert_size || aspect_ratio!=current_aspect_ratio || frame_rate!=current_frame_rate) { // If horizontal/vertical size, framerate and/or aspect // ratio are ilegal, we discard the // whole sequence info. if (vert_size >= 288 && vert_size <= 1088 && hor_size >= 352 && hor_size <= 1920 && hor_size / vert_size >= 352/576 && hor_size / vert_size <= 2 && frame_rate>0 && frame_rate<9 && aspect_ratio>0 && aspect_ratio<5) { mprint ("\n\nNew video information found"); if (pts_set==2) { unsigned cur_sec = (unsigned) ((current_pts - min_pts) / MPEG_CLOCK_FREQ); mprint (" at %02u:%02u",cur_sec/60, cur_sec % 60); } mprint ("\n"); mprint ("[%u * %u] [AR: %s] [FR: %s]", hor_size,vert_size, aspect_ratio_types[aspect_ratio], framerates_types[frame_rate]); // No newline, force the output of progressive info in picture // info part. current_progressive_sequence = 2; current_hor_size=hor_size; current_vert_size=vert_size; current_aspect_ratio=aspect_ratio; current_frame_rate=frame_rate; current_fps = framerates_values[current_frame_rate]; activity_video_info (hor_size,vert_size, aspect_ratio_types[aspect_ratio], framerates_types[frame_rate]); } else { dbg_print(CCX_DMT_VERBOSE, "\nInvalid sequence header:\n"); dbg_print(CCX_DMT_VERBOSE, "V: %u H: %u FR: %u AS: %u\n", vert_size, hor_size, frame_rate, aspect_ratio); esstream->error = 1; return 0; } } // Read complete return 1; }
int main(int argc, char **argv) { FILE *fp; char *fpname; int i, len; int bitpos = 0, bit_ = 0, bit; char Bit = 0 /*,Bit0*/; float l = 0, l0 = 0, bitslen = 0; #ifdef CYGWIN _setmode(fileno(stdin), _O_BINARY); // _setmode(_fileno(stdin), _O_BINARY); setbuf(stdout, NULL); #endif fpname = argv[0]; ++argv; while ((*argv) && (!wavloaded)) { if ( (strcmp(*argv, "-h") == 0) || (strcmp(*argv, "--help") == 0) ) { fprintf(stderr, "%s [options] audio.wav\n", fpname); fprintf(stderr, " options:\n"); fprintf(stderr, " -r, --raw\n"); return 0; } /* else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) { option_verbose = 1; } */ else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) { option_raw = 1; } else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) { option_inv = 1; } else { fp = fopen(*argv, "rb"); if (fp == NULL) { fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv); return -1; } wavloaded = 1; } ++argv; } if (!wavloaded) fp = stdin; i = read_wav_header(fp); if (i) { fclose(fp); return -1; } bitpos = 0; while (!read_bits(fp, &Bit, &l)) { if (l < 0.1) { bitslen = 0; continue; } if ((l0 < BIT01 && l < BIT01) || (l0 >= BIT01 && l >= BIT01)) { bitslen += l; } else { //fprintf(stderr, " %.1f\n", bitslen); if (Bit < 'a') bit = 0; else bit = 1; // gesucht ist Bit zuvor len = (int)(bitslen+0.5); if (len < SYNC) { for (i = 0; i < len/2; i++) { //printf("%d", bit); if (bitpos < BAUD+10) { bitframe[bitpos] = bit; } else { /* */ } bitpos++; } //printf(" %.1f=%d ", bitslen, len); } bitslen = l; } l0 = l; if (Bit < 'a') { bit_++; } else { if (bit_> SYNC) { if (bitpos < BAUD) print_frame((bitpos+7)/10); bitframe[0] = 1; bitpos = 1; //printf("\n1"); } bit_ = 0; } } printf("\n"); fclose(fp); return 0; }
static void decode_channel(const uint8_t *base_addr, const channel_block &block, surface<float> *surf, const std::vector<plane> &planes, const std::pair<float, float> range, bool negative_line_stride) { block_iterator it(block.w, block.h, surf); uint32_t n_blocks_in_line = (surf->width() / block.w); uint32_t n_block_lines = (surf->height() / block.h); // We need to support negative line stride. std::vector<std::pair<std::ptrdiff_t , std::ptrdiff_t >> line_offsets; for (const auto & plane : planes ) { if (negative_line_stride) { std::ptrdiff_t line_stride = -static_cast<std::ptrdiff_t>(plane.line_stride); // Each line is still left to right. line_offsets.emplace_back(line_stride, plane.size + line_stride); } else { line_offsets.emplace_back(plane.line_stride, 0); } } // We need to preprocess the sample array to support continuation samples. std::vector<sample> samples; for (std::size_t i = 0; i < block.samples.size(); ) { const xyuv::sample &sample = block.samples[i]; if (!sample.has_continuation) { samples.push_back(sample); i++; } else { // Create a descriptor block containing all the bits of the samples. xyuv::sample sample_descriptor; sample_descriptor.integer_bits = 0; sample_descriptor.fractional_bits = 0; sample_descriptor.has_continuation = true; samples.push_back(sample_descriptor); size_t descriptor_pos = samples.size() -1; do { // Update descriptor samples[descriptor_pos].integer_bits += block.samples[i].integer_bits; samples[descriptor_pos].fractional_bits += block.samples[i].fractional_bits; samples.push_back(block.samples[i]); } while(block.samples[i++].has_continuation); } } for (uint32_t line = 0; line < n_block_lines; line++) { for (uint32_t b = 0; b < n_blocks_in_line; b++) { for (std::size_t s = 0; s < samples.size(); ) { uint8_t integer_bits = samples[s].integer_bits; uint8_t fractional_bits = samples[s].fractional_bits; // If we hit a continuation block here, it means that we have the // Total bits descriptor and should skip it for the purpose of actual loading. if (samples[s].has_continuation) { s++; } unorm_t unorm = 0; do { const xyuv::sample &sample = samples[s]; const uint8_t * ptr_to_line = // Start with offset to frame base_addr + // Add offset to lowest byte in plane. planes[sample.plane].base_offset + // Add the size of the plane if applicable. line_offsets[sample.plane].second + // Add offset to current line. get_line(line, planes[sample.plane].interleave_mode, n_block_lines) * line_offsets[sample.plane].first; // Read bits reads bits from MSb integer to LSb fractional bit. read_bits( unorm, ptr_to_line, b * planes[sample.plane].block_stride + sample.offset, sample.integer_bits + sample.fractional_bits); } while (samples[s++].has_continuation); float *value = it.advance(); *value = from_unorm(unorm, integer_bits, fractional_bits, range); } } } }
int h264_decode_seq_parameter_set(elementary_stream_t *st, bitstream_t *bs) { uint32_t profile_idc, level_idc, poc_type; uint32_t sps_id, tmp, i, width, height; uint32_t cbpsize, mbs_only_flag, aff; uint32_t max_frame_num_bits; uint32_t crop_left, crop_right, crop_top, crop_bottom; h264_private_t *p; h264_sps_t *sps; if ((p = st->es_priv) == NULL) { p = st->es_priv = calloc(1, sizeof(h264_private_t)); p->start = dispatch_clock; } profile_idc = read_bits(bs, 8); skip_bits1(bs); //constraint_set0_flag skip_bits1(bs); //constraint_set1_flag skip_bits1(bs); //constraint_set2_flag skip_bits1(bs); //constraint_set3_flag skip_bits(bs, 4); // reserved level_idc = read_bits(bs, 8); sps_id = read_golomb_ue(bs); if(sps_id >= MAX_SPS_COUNT) return -1; sps = &p->sps[sps_id]; i = 0; cbpsize = -1; while (h264_lev2cpbsize[i][0] != -1) { if (h264_lev2cpbsize[i][0] >= level_idc) { cbpsize = h264_lev2cpbsize[i][1]; break; } i++; } if (cbpsize == -1) return -1; if (profile_idc >= 100){ //high profile tmp = read_golomb_ue(bs); if (tmp == 3) //chroma_format_idc read_bits1(bs); //residual_color_transform_flag read_golomb_ue(bs); //bit_depth_luma_minus8 read_golomb_ue(bs); //bit_depth_chroma_minus8 read_bits1(bs); //transform_bypass if(read_bits1(bs)) { /* Scaling matrices */ decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 16); decode_scaling_list(bs, 64); decode_scaling_list(bs, 64); } } max_frame_num_bits = read_golomb_ue(bs) + 4; poc_type = read_golomb_ue(bs); // pic_order_cnt_type if(poc_type == 0){ read_golomb_ue(bs); } else if(poc_type == 1){ skip_bits1(bs); read_golomb_se(bs); read_golomb_se(bs); tmp = read_golomb_ue(bs); /* poc_cycle_length */ for(i = 0; i < tmp; i++) read_golomb_se(bs); }else if(poc_type != 2){ /* Illegal poc */ return -1; } tmp = read_golomb_ue(bs); read_bits1(bs); width = read_golomb_ue(bs) + 1; /* mb width */ height = read_golomb_ue(bs) + 1; /* mb height */ mbs_only_flag = read_bits1(bs); aff = 0; if(!mbs_only_flag) aff = read_bits1(bs); read_bits1(bs); /* CROP */ crop_left = crop_right = crop_top = crop_bottom = 0; if (read_bits1(bs)){ crop_left = read_golomb_ue(bs) * 2; crop_right = read_golomb_ue(bs) * 2; crop_top = read_golomb_ue(bs) * 2; crop_bottom = read_golomb_ue(bs) * 2; } if (read_bits1(bs)) /* vui present */ if (decode_vui(sps, bs)) return -1; sps->max_frame_num_bits = max_frame_num_bits; sps->mbs_only_flag = mbs_only_flag; sps->aff = aff; sps->cbpsize = cbpsize * 125; /* Convert from kbit to bytes */ sps->width = width * 16 - crop_left - crop_right; sps->height = height * 16 - crop_top - crop_bottom; sps->valid = 1; return 0; }
// Parse the user data for captions. The udtype variable denotes // to which type of data it belongs: // 0 .. sequence header // 1 .. GOP header // 2 .. picture header // Return TRUE if the data parsing finished, FALSE otherwise. // estream->pos is advanced. Data is only processed if ustream->error // is FALSE, parsing can set ustream->error to TRUE. int user_data(struct lib_cc_decode *ctx, struct bitstream *ustream, int udtype, struct cc_subtitle *sub) { dbg_print(CCX_DMT_VERBOSE, "user_data(%d)\n", udtype); // Shall not happen if (ustream->error || ustream->bitsleft <= 0) { // ustream->error=1; return 0; // Actually discarded on call. // CFS: Seen in a Wobble edited file. // fatal(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!"); } // Do something ctx->stat_numuserheaders++; //header+=4; unsigned char *ud_header = next_bytes(ustream, 4); if (ustream->error || ustream->bitsleft <= 0) { return 0; // Actually discarded on call. // CFS: Seen in Stick_VHS.mpg. // fatal(CCX_COMMON_EXIT_BUG_BUG, "user_data: Impossible!"); } // DVD CC header, see // <http://www.theneitherworld.com/mcpoodle/SCC_TOOLS/DOCS/SCC_FORMAT.HTML> if ( !memcmp(ud_header,"\x43\x43", 2 ) ) { ctx->stat_dvdccheaders++; // Probably unneeded, but keep looking for extra caption blocks int maybeextracb = 1; read_bytes(ustream, 4); // "43 43 01 F8" unsigned char pattern_flag = (unsigned char) read_bits(ustream,1); read_bits(ustream,1); int capcount=(int) read_bits(ustream,5); int truncate_flag = (int) read_bits(ustream,1); // truncate_flag - one CB extra int field1packet = 0; // expect Field 1 first if (pattern_flag == 0x00) field1packet=1; // expect Field 1 second dbg_print(CCX_DMT_VERBOSE, "Reading %d%s DVD CC segments\n", capcount, (truncate_flag?"+1":"")); capcount += truncate_flag; // This data comes before the first frame header, so // in order to get the correct timing we need to set the // current time to one frame after the maximum time of the // last GOP. Only useful when there are frames before // the GOP. if (ctx->timing->fts_max > 0) ctx->timing->fts_now = ctx->timing->fts_max + (LLONG) (1000.0/current_fps); int rcbcount = 0; for (int i=0; i<capcount; i++) { for (int j=0;j<2;j++) { unsigned char data[3]; data[0]=read_u8(ustream); data[1]=read_u8(ustream); data[2]=read_u8(ustream); // Obey the truncate flag. if ( truncate_flag && i == capcount-1 && j == 1 ) { maybeextracb = 0; break; } /* Field 1 and 2 data can be in either order, with marker bytes of \xff and \xfe Since markers can be repeated, use pattern as well */ if ((data[0]&0xFE) == 0xFE) // Check if valid { if (data[0]==0xff && j==field1packet) data[0]=0x04; // Field 1 else data[0]=0x05; // Field 2 do_cb(ctx, data, sub); rcbcount++; } else { dbg_print(CCX_DMT_VERBOSE, "Illegal caption segment - stop here.\n"); maybeextracb = 0; break; } } } // Theoretically this should not happen, oh well ... // Deal with extra closed captions some DVD have. int ecbcount = 0; while ( maybeextracb && (next_u8(ustream)&0xFE) == 0xFE ) { for (int j=0;j<2;j++) { unsigned char data[3]; data[0]=read_u8(ustream); data[1]=read_u8(ustream); data[2]=read_u8(ustream); /* Field 1 and 2 data can be in either order, with marker bytes of \xff and \xfe Since markers can be repeated, use pattern as well */ if ((data[0]&0xFE) == 0xFE) // Check if valid { if (data[0]==0xff && j==field1packet) data[0]=0x04; // Field 1 else data[0]=0x05; // Field 2 do_cb(ctx, data, sub); ecbcount++; } else { dbg_print(CCX_DMT_VERBOSE, "Illegal (extra) caption segment - stop here.\n"); maybeextracb = 0; break; } } } dbg_print(CCX_DMT_VERBOSE, "Read %d/%d DVD CC blocks\n", rcbcount, ecbcount); } // SCTE 20 user data else if (!ctx->noscte20 && ud_header[0] == 0x03) { if ((ud_header[1]&0x7F) == 0x01) { unsigned char cc_data[3*31+1]; // Maximum cc_count is 31 ctx->stat_scte20ccheaders++; read_bytes(ustream, 2); // "03 01" unsigned cc_count = (unsigned int) read_bits(ustream,5); dbg_print(CCX_DMT_VERBOSE, "Reading %d SCTE 20 CC blocks\n", cc_count); unsigned field_number; unsigned cc_data1; unsigned cc_data2; for (unsigned j=0;j<cc_count;j++) { skip_bits(ustream,2); // priority - unused field_number = (unsigned int) read_bits(ustream,2); skip_bits(ustream,5); // line_offset - unused cc_data1 = (unsigned int) read_bits(ustream,8); cc_data2 = (unsigned int) read_bits(ustream,8); read_bits(ustream,1); // TODO: Add syntax check */ if (ustream->bitsleft < 0) fatal(CCX_COMMON_EXIT_BUG_BUG, "In user_data: ustream->bitsleft < 0. Cannot continue."); // Field_number is either // 0 .. forbidden // 1 .. field 1 (odd) // 2 .. field 2 (even) // 3 .. repeated, from repeat_first_field, effectively field 1 if (field_number < 1) { // 0 is invalid cc_data[j*3]=0x00; // Set to invalid cc_data[j*3+1]=0x00; cc_data[j*3+2]=0x00; } else { // Treat field_number 3 as 1 field_number = (field_number - 1) & 0x01; // top_field_first also affects to which field the caption // belongs. if(!ctx->top_field_first) field_number ^= 0x01; cc_data[j*3]=0x04|(field_number); cc_data[j*3+1]=reverse8(cc_data1); cc_data[j*3+2]=reverse8(cc_data2); } } cc_data[cc_count*3]=0xFF; store_hdcc(ctx, cc_data, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub); dbg_print(CCX_DMT_VERBOSE, "Reading SCTE 20 CC blocks - done\n"); } // reserved - unspecified } // ReplayTV 4000/5000 caption header - parsing information // derived from CCExtract.bdl else if ( (ud_header[0] == 0xbb //ReplayTV 4000 || ud_header[0] == 0x99) //ReplayTV 5000 && ud_header[1] == 0x02 ) { unsigned char data[3]; if (ud_header[0]==0xbb) ctx->stat_replay4000headers++; else ctx->stat_replay5000headers++; read_bytes(ustream, 2); // "BB 02" or "99 02" data[0]=0x05; // Field 2 data[1]=read_u8(ustream); data[2]=read_u8(ustream); do_cb(ctx, data, sub); read_bytes(ustream, 2); // Skip "CC 02" for R4000 or "AA 02" for R5000 data[0]=0x04; // Field 1 data[1]=read_u8(ustream); data[2]=read_u8(ustream); do_cb(ctx, data, sub); } // HDTV - see A/53 Part 4 (Video) else if ( !memcmp(ud_header,"\x47\x41\x39\x34", 4 ) ) { ctx->stat_hdtv++; read_bytes(ustream, 4); // "47 41 39 34" unsigned char type_code = read_u8(ustream); if (type_code==0x03) // CC data. { skip_bits(ustream,1); // reserved unsigned char process_cc_data = (unsigned char) read_bits(ustream,1); skip_bits(ustream,1); // additional_data - unused unsigned char cc_count = (unsigned char) read_bits(ustream,5); read_bytes(ustream, 1); // "FF" if (process_cc_data) { dbg_print(CCX_DMT_VERBOSE, "Reading %d HDTV CC blocks\n", cc_count); int proceed = 1; unsigned char *cc_data = read_bytes(ustream, cc_count*3); if (ustream->bitsleft < 0) fatal(CCX_COMMON_EXIT_BUG_BUG, "In user_data: ustream->bitsleft < 0. Cannot continue.\n"); // Check for proper marker - This read makes sure that // cc_count*3+1 bytes are read and available in cc_data. if (read_u8(ustream)!=0xFF) proceed=0; if (!proceed) { dbg_print(CCX_DMT_VERBOSE, "\rThe following payload is not properly terminated.\n"); dump (CCX_DMT_VERBOSE, cc_data, cc_count*3+1, 0, 0); } dbg_print(CCX_DMT_VERBOSE, "Reading %d HD CC blocks\n", cc_count); // B-frames might be (temporal) before or after the anchor // frame they belong to. Store the buffer until the next anchor // frame occurs. The buffer will be flushed (sorted) in the // picture header (or GOP) section when the next anchor occurs. // Please note we store the current value of the global // fts_now variable (and not get_fts()) as we are going to // re-create the timeline in process_hdcc() (Slightly ugly). store_hdcc(ctx, cc_data, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub); dbg_print(CCX_DMT_VERBOSE, "Reading HDTV blocks - done\n"); } } // reserved - additional_cc_data } // DVB closed caption header for Dish Network (Field 1 only) */ else if ( !memcmp(ud_header,"\x05\x02", 2 ) ) { // Like HDTV (above) Dish Network captions can be stored at each // frame, but maximal two caption blocks per frame and only one // field is stored. // To process this with the HDTV framework we create a "HDTV" caption // format compatible array. Two times 3 bytes plus one for the 0xFF // marker at the end. Pre-init to field 1 and set the 0xFF marker. static unsigned char dishdata[7] = {0x04, 0, 0, 0x04, 0, 0, 0xFF}; int cc_count; dbg_print(CCX_DMT_VERBOSE, "Reading Dish Network user data\n"); ctx->stat_dishheaders++; read_bytes(ustream, 2); // "05 02" // The next bytes are like this: // header[2] : ID: 0x04 (MPEG?), 0x03 (H264?) // header[3-4]: Two byte counter (counting (sub-)GOPs?) // header[5-6]: Two bytes, maybe checksum? // header[7]: Pattern type // on B-frame: 0x02, 0x04 // on I-/P-frame: 0x05 unsigned char id = read_u8(ustream); unsigned dishcount = read_u16(ustream); unsigned something = read_u16(ustream); unsigned char type = read_u8(ustream); dbg_print(CCX_DMT_PARSE, "DN ID: %02X Count: %5u Unknown: %04X Pattern: %X", id, dishcount, something, type); unsigned char hi; // The following block needs 4 to 6 bytes starting from the // current position unsigned char *dcd = ustream->pos; // dish caption data switch (type) { case 0x02: // Two byte caption - always on B-frame // The following 4 bytes are: // 0 : 0x09 // 1-2: caption block // 3 : REPEAT - 02: two bytes // - 04: four bytes (repeat first two) dbg_print(CCX_DMT_PARSE, "\n02 %02X %02X:%02X - R:%02X :", dcd[0], dcd[1], dcd[2], dcd[3]); cc_count = 1; dishdata[1]=dcd[1]; dishdata[2]=dcd[2]; dbg_print(CCX_DMT_PARSE, "%s", debug_608_to_ASC( dishdata, 0) ); type=dcd[3]; // repeater (0x02 or 0x04) hi = dishdata[1] & 0x7f; // Get only the 7 low bits if (type==0x04 && hi<32) // repeat (only for non-character pairs) { cc_count = 2; dishdata[3]=0x04; // Field 1 dishdata[4]=dishdata[1]; dishdata[5]=dishdata[2]; dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) ); } else { dbg_print(CCX_DMT_PARSE, ":\n"); } dishdata[cc_count*3] = 0xFF; // Set end marker store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub); // Ignore 3 (0x0A, followed by two unknown) bytes. break; case 0x04: // Four byte caption - always on B-frame // The following 5 bytes are: // 0 : 0x09 // 1-2: caption block // 3-4: caption block dbg_print(CCX_DMT_PARSE, "\n04 %02X %02X:%02X:%02X:%02X :", dcd[0], dcd[1], dcd[2], dcd[3], dcd[4]); cc_count = 2; dishdata[1]=dcd[1]; dishdata[2]=dcd[2]; dishdata[3]=0x04; // Field 1 dishdata[4]=dcd[3]; dishdata[5]=dcd[4]; dishdata[6] = 0xFF; // Set end marker dbg_print(CCX_DMT_PARSE, "%s", debug_608_to_ASC( dishdata, 0) ); dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) ); store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub); // Ignore 4 (0x020A, followed by two unknown) bytes. break; case 0x05: // Buffered caption - always on I-/P-frame // The following six bytes are: // 0 : 0x04 // - the following are from previous 0x05 caption header - // 1 : prev dcd[2] // 2-3: prev dcd[3-4] // 4-5: prev dcd[5-6] dbg_print(CCX_DMT_PARSE, " - %02X pch: %02X %5u %02X:%02X\n", dcd[0], dcd[1], (unsigned)dcd[2]*256+dcd[3], dcd[4], dcd[5]); dcd+=6; // Skip these 6 bytes // Now one of the "regular" 0x02 or 0x04 captions follows dbg_print(CCX_DMT_PARSE, "%02X %02X %02X:%02X", dcd[0], dcd[1], dcd[2], dcd[3]); type=dcd[0]; // Number of caption bytes (0x02 or 0x04) cc_count = 1; dishdata[1]=dcd[2]; dishdata[2]=dcd[3]; dcd+=4; // Skip the first 4 bytes. if (type==0x02) { type=dcd[0]; // repeater (0x02 or 0x04) dcd++; // Skip the repeater byte. dbg_print(CCX_DMT_PARSE, " - R:%02X :%s", type, debug_608_to_ASC( dishdata, 0) ); hi = dishdata[1] & 0x7f; // Get only the 7 low bits if (type==0x04 && hi<32) { cc_count = 2; dishdata[3]=0x04; // Field 1 dishdata[4]=dishdata[1]; dishdata[5]=dishdata[2]; dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) ); } else { dbg_print(CCX_DMT_PARSE, ":\n"); } dishdata[cc_count*3] = 0xFF; // Set end marker } else { dbg_print(CCX_DMT_PARSE, ":%02X:%02X ", dcd[0], dcd[1]); cc_count = 2; dishdata[3]=0x04; // Field 1 dishdata[4]=dcd[0]; dishdata[5]=dcd[1]; dishdata[6] = 0xFF; // Set end marker dbg_print(CCX_DMT_PARSE, ":%s", debug_608_to_ASC( dishdata, 0) ); dbg_print(CCX_DMT_PARSE, "%s:\n", debug_608_to_ASC( dishdata+3, 0) ); } store_hdcc(ctx, dishdata, cc_count, ctx->timing->current_tref, ctx->timing->fts_now, sub); // Ignore 3 (0x0A, followed by 2 unknown) bytes. break; default: // printf ("Unknown?\n"); break; } // switch dbg_print(CCX_DMT_VERBOSE, "Reading Dish Network user data - done\n"); } // CEA 608 / aka "Divicom standard", see: // http://www.pixeltools.com/tech_tip_closed_captioning.html else if ( !memcmp(ud_header,"\x02\x09", 2 ) ) { // Either a documentation or more examples are needed. ctx->stat_divicom++; unsigned char data[3]; read_bytes(ustream, 2); // "02 09" read_bytes(ustream, 2); // "80 80" ??? read_bytes(ustream, 2); // "02 0A" ??? data[0]=0x04; // Field 1 data[1]=read_u8(ustream); data[2]=read_u8(ustream); do_cb(ctx, data, sub); // This is probably incomplete! } // GXF vbi OEM code else if ( !memcmp(ud_header,"\x73\x52\x21\x06", 4 ) ) { int udatalen = ustream->end - ustream->pos; uint16_t line_nb; uint8_t line_type; uint8_t field = 1; read_bytes(ustream, 4); //skip header code read_bytes(ustream, 2); //skip data length line_nb = read_bits(ustream, 16); line_type = read_u8(ustream); field = (line_type & 0x03); if(field == 0) mprint("MPEG:VBI: Invalid field\n"); line_type = line_type >> 2; if(line_type != 1) mprint("MPEG:VBI: only support Luma line\n"); if (udatalen < 720) mprint("MPEG:VBI: Minimum 720 bytes in luma line required\n"); decode_vbi(ctx, field, ustream->pos, 720, sub); dbg_print(CCX_DMT_VERBOSE, "GXF (vbi line %d) user data:\n", line_nb); }
unsigned int read_bits1(bitstream_t *bs) { return read_bits(bs, 1); }
/*! * \brief Parse a mp4 file. * \param *video A pointer to a VideoFile_t structure. * \return retcode 1 if succeed, 0 otherwise. * * This parser is based on the 'ISO/IEC 13818-1' international standard, part 1: * 'Transmission multiplexing and synchronization'. */ int ps_fileParse(VideoFile_t *video) { TRACE_INFO(MPS, BLD_GREEN "ps_fileParse()\n" CLR_RESET); int retcode = SUCCESS; int sid = 0; // Init bitstream to parse container infos Bitstream_t *bitstr = init_bitstream(video, NULL); if (bitstr != NULL) { // Init bitstream_map to store container infos retcode = init_bitstream_map(&video->tracks_audio[0], 999999); retcode = init_bitstream_map(&video->tracks_video[0], 999999); if (retcode == SUCCESS) { video->tracks_audio[0]->stream_type = stream_AUDIO; video->tracks_audio[0]->stream_level = stream_level_PES; video->tracks_audio[0]->stream_codec = CODEC_MPEG_L3; video->tracks_audio[0]->sample_alignment = false; video->tracks_video[0]->stream_type = stream_VIDEO; video->tracks_video[0]->stream_level = stream_level_PES; video->tracks_video[0]->stream_codec = CODEC_MPEG12; video->tracks_video[0]->sample_alignment = false; // Read bitstream while (retcode == SUCCESS && (bitstream_get_absolute_byte_offset(bitstr) + 4) < video->file_size && next_bits(bitstr, 32) != PES_PROGRAM_END) { PackHeader_t pack_header; SystemHeader_t system_header; if (read_bits(bitstr, 32) == PES_PACK_HEADER) { // Parse pack & system header retcode = parse_pack_header(bitstr, &pack_header, &system_header); // Then loop on PES while (retcode == SUCCESS && (bitstream_get_absolute_byte_offset(bitstr) + 4) < video->file_size && next_bits(bitstr, 32) != PES_PACK_HEADER && next_bits(bitstr, 32) != PES_PROGRAM_END) { // Init PesPacket_t pes_packet; ProgramStreamMap_t pes_streammap; ProgramStreamDirectory_t pes_streamdirectory; // Parse start code pes_packet.packet_start_offset = bitstream_get_absolute_byte_offset(bitstr); pes_packet.packet_start_code = read_bits(bitstr, 24); pes_packet.stream_id = (uint8_t)read_bits(bitstr, 8); if (pes_packet.packet_start_code == PES_PACKETSTARTCODE) { switch (pes_packet.stream_id) { case SID_PROGRAM_STREAM_MAP: retcode = parse_program_stream_map(bitstr, &pes_streammap); break; case SID_PROGRAM_STREAM_DIRECTORY: retcode = parse_program_stream_directory(bitstr, &pes_streamdirectory); break; case SID_PADDING: retcode = parse_pes_padding(bitstr, &pes_packet); break; case SID_PRIVATE_STREAM_1: TRACE_2(MPS, BLD_GREEN "Private Stream 1 PES" CLR_RESET " @ %i\n", pes_packet.packet_start_offset); retcode = skip_pes(bitstr, &pes_packet); break; case SID_PRIVATE_STREAM_2: TRACE_2(MPS, BLD_GREEN "Private Stream 2 PES" CLR_RESET " @ %i\n", pes_packet.packet_start_offset); retcode = skip_pes(bitstr, &pes_packet); break; case SID_VIDEO: TRACE_INFO(MPS, BLD_GREEN "parse_pes_video()" CLR_RESET " @ %i\n", pes_packet.packet_start_offset); retcode = parse_pes(bitstr, &pes_packet); //print_pes(&pes_packet); // Set sample into the bitstream_map video->tracks_video[0]->sample_count++; sid = video->tracks_video[0]->sample_count; if (sid < 999999) { video->tracks_video[0]->sample_type[sid] = sample_VIDEO; video->tracks_video[0]->sample_size[sid] = pes_packet.PES_packet_length + 6; video->tracks_video[0]->sample_offset[sid] = pes_packet.packet_start_offset; video->tracks_video[0]->sample_pts[sid] = pes_packet.PTS; video->tracks_video[0]->sample_dts[sid] = pes_packet.DTS; } break; case SID_AUDIO: TRACE_INFO(MPS, BLD_GREEN "parse_pes_audio()" CLR_RESET " @ %i\n", pes_packet.packet_start_offset); retcode = parse_pes(bitstr, &pes_packet); //print_pes(&pes_packet); // Set sample into the bitstream_map video->tracks_audio[0]->sample_count++; sid = video->tracks_audio[0]->sample_count; if (sid < 999999) { video->tracks_audio[0]->sample_type[sid] = sample_AUDIO; video->tracks_audio[0]->sample_size[sid] = pes_packet.PES_packet_length + 6; video->tracks_audio[0]->sample_offset[sid] = pes_packet.packet_start_offset; video->tracks_audio[0]->sample_pts[sid] = pes_packet.PTS; video->tracks_audio[0]->sample_dts[sid] = pes_packet.DTS; } break; default: TRACE_WARNING(MPS, "Unknown PES type (0x%06X%02X) @ %i\n", pes_packet.packet_start_code, pes_packet.stream_id, pes_packet.packet_start_offset); retcode = skip_pes(bitstr, &pes_packet); break; } } else { TRACE_ERROR(MPS, "No valid packet_start_code at %i\n", pes_packet.packet_start_offset); retcode = FAILURE; } } } else { TRACE_ERROR(MPS, "No pack header\n"); retcode = FAILURE; } } } // Free bitstream free_bitstream(&bitstr); } return retcode; }
/*! * \brief Parse a system header structure. * \param *bitstr The bitstream to use. * \param *system_header A pointer to a system_header structure. * \return 1 if succeed, 0 otherwise. * * From 'ISO/IEC 13818-1' specification: * 2.5.3.5 System header. * Table 2-34 – Program Stream system header */ static int parse_system_header(Bitstream_t *bitstr, PesHeader_t *header, SystemHeader_t *packet) { int retcode = SUCCESS; TRACE_INFO(MPS, BLD_GREEN "parse_system_header()" CLR_RESET " @ %lli", header->offset_start); MARKER_BIT packet->rate_bound = read_bits(bitstr, 22); MARKER_BIT packet->audio_bound = read_bits(bitstr, 6); packet->fixed_flag = read_bits(bitstr, 1); packet->CSPS_flag = read_bits(bitstr, 1); packet->system_audio_lock_flag = read_bits(bitstr, 1); packet->system_video_lock_flag = read_bits(bitstr, 1); MARKER_BIT packet->video_bound = read_bits(bitstr, 5); packet->packet_rate_restriction_flag = read_bits(bitstr, 1); /*unsigned reserved_bits =*/ read_bits(bitstr, 7); // stack it? while (next_bit(bitstr) == 1) { packet->stream_id = read_bits(bitstr, 8); MARKER_BIT MARKER_BIT packet->PSTD_buffer_bound_scale = read_bits(bitstr, 1); packet->PSTD_buffer_size_bound = read_bits(bitstr, 13); } return retcode; }
/*! * \brief Read prediction informations for current macroblock. * \param *dc The current DecodingContext. * \param *mb The current macroblock. * * Intra prediction infos are a table containing prediction mode for each blocks. * Inter prediction infos are motion vectors. */ static void mb_pred(DecodingContext_t *dc, Macroblock_t *mb) { TRACE_INFO(MB, " > " BLD_GREEN "mb_pred()\n" CLR_RESET); if (mb->MbPartPredMode[0] == Intra_4x4 || mb->MbPartPredMode[0] == Intra_8x8 || mb->MbPartPredMode[0] == Intra_16x16) { if (mb->MbPartPredMode[0] == Intra_4x4) { // Read intra prediction mode for all 16 4x4 luma blocks unsigned int luma4x4BlkIdx = 0; for (luma4x4BlkIdx = 0; luma4x4BlkIdx < 16; luma4x4BlkIdx++) { if (dc->entropy_coding_mode_flag) mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = read_ae(dc, SE_prev_intraxxx_pred_mode_flag); else mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] = read_bit(dc->bitstr); if (mb->prev_intra4x4_pred_mode_flag[luma4x4BlkIdx] == false) { if (dc->entropy_coding_mode_flag) mb->rem_intra4x4_pred_mode[luma4x4BlkIdx] = read_ae(dc, SE_rem_intraxxx_pred_mode); else mb->rem_intra4x4_pred_mode[luma4x4BlkIdx] = read_bits(dc->bitstr, 3); } } } else if (mb->MbPartPredMode[0] == Intra_8x8) { // Read intra prediction mode for all 4 8x8 luma blocks unsigned int luma8x8BlkIdx = 0; for (luma8x8BlkIdx = 0; luma8x8BlkIdx < 4; luma8x8BlkIdx++) { if (dc->entropy_coding_mode_flag) mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] = read_ae(dc, SE_prev_intraxxx_pred_mode_flag); else mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] = read_bit(dc->bitstr); if (mb->prev_intra8x8_pred_mode_flag[luma8x8BlkIdx] == false) { if (dc->entropy_coding_mode_flag) mb->rem_intra8x8_pred_mode[luma8x8BlkIdx] = read_ae(dc, SE_rem_intraxxx_pred_mode); else mb->rem_intra8x8_pred_mode[luma8x8BlkIdx] = read_bits(dc->bitstr, 3); } } } // Read intra prediction mode for chroma blocks if (dc->ChromaArrayType == 1 || dc->ChromaArrayType == 2) { if (dc->entropy_coding_mode_flag) mb->IntraChromaPredMode = read_ae(dc, SE_intra_chroma_pred_mode); else mb->IntraChromaPredMode = read_ue(dc->bitstr); } } else if (mb->MbPartPredMode[0] != Direct) { // ref_idx_l0 unsigned int mbPartIdx = 0; for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if ((dc->active_slice->num_ref_idx_l0_active_minus1 > 0 || dc->active_slice->mb_field_decoding_flag != dc->active_slice->field_pic_flag) && MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L1) { if (dc->entropy_coding_mode_flag) mb->ref_idx_l0[mbPartIdx] = read_ae(dc, SE_ref_idx_lx); else mb->ref_idx_l0[mbPartIdx] = read_te(dc->bitstr, 0); } } // ref_idx_l1 for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if ((dc->active_slice->num_ref_idx_l1_active_minus1 > 0 || dc->active_slice->mb_field_decoding_flag != dc->active_slice->field_pic_flag) && MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L0) { if (dc->entropy_coding_mode_flag) mb->ref_idx_l1[mbPartIdx] = read_ae(dc, SE_ref_idx_lx); else mb->ref_idx_l1[mbPartIdx] = read_te(dc->bitstr, 0); } } // mvd_l0 for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if (MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L1) { if (dc->entropy_coding_mode_flag) { mb->mvd_l0[mbPartIdx][0][0] = read_ae(dc, SE_mvd_lx0); mb->mvd_l0[mbPartIdx][0][1] = read_ae(dc, SE_mvd_lx1); } else { mb->mvd_l0[mbPartIdx][0][0] = read_te(dc->bitstr, 0); mb->mvd_l0[mbPartIdx][0][1] = read_te(dc->bitstr, 0); } } } // mvd_l1 for (mbPartIdx = 0; mbPartIdx < mb->NumMbPart; mbPartIdx++) { if (MbPartPredMode(mb, dc->active_slice->slice_type, mbPartIdx) != Pred_L0) { if (dc->entropy_coding_mode_flag) { mb->mvd_l1[mbPartIdx][0][0] = read_ae(dc, SE_mvd_lx0); mb->mvd_l1[mbPartIdx][0][1] = read_ae(dc, SE_mvd_lx1); } else { mb->mvd_l1[mbPartIdx][0][0] = read_te(dc->bitstr, 0); mb->mvd_l1[mbPartIdx][0][1] = read_te(dc->bitstr, 0); } } } } }
/*! * \brief Parse a program stream directory structure. * \param *bitstr The bitstream to use. * \param *packet A program stream directory structure. * \return 1 if succeed, 0 otherwise. * * From 'ISO/IEC 13818-1' specification: * 2.5.5 Program Stream directory * Table 2-36 – Program Stream directory packet */ static int parse_program_stream_directory(Bitstream_t *bitstr, PesHeader_t *header, ProgramStreamDirectory_t *packet) { TRACE_INFO(MPS, BLD_GREEN "parse_program_stream_directory()" CLR_RESET " @ %lli", header->offset_start); int retcode = SUCCESS; packet->number_of_access_units = read_bits(bitstr, 15); MARKER_BIT packet->prev_directory_offset = read_bits(bitstr, 15) << 30; MARKER_BIT packet->prev_directory_offset += read_bits(bitstr, 15) << 15; MARKER_BIT packet->prev_directory_offset += read_bits(bitstr, 15); MARKER_BIT packet->next_directory_offset = read_bits(bitstr, 15) << 30; MARKER_BIT packet->next_directory_offset += read_bits(bitstr, 15) << 15; MARKER_BIT packet->next_directory_offset += read_bits(bitstr, 15); MARKER_BIT for (uint16_t i = 0; i < packet->number_of_access_units; i++) { // TODO stack it? packet->packet_stream_id = read_bits(bitstr, 8); packet->PES_header_position_offset_sign = read_bit(bitstr); packet->PES_header_position_offset = read_bits(bitstr, 14) << 30; MARKER_BIT packet->PES_header_position_offset += read_bits(bitstr, 15) << 15; MARKER_BIT packet->PES_header_position_offset += read_bits(bitstr, 15); MARKER_BIT packet->reference_offset = read_bits(bitstr, 16); MARKER_BIT /*unsigned reserved1 =*/ read_bits(bitstr, 3); packet->PTS = read_bits(bitstr, 3) << 30; MARKER_BIT packet->PTS += read_bits(bitstr, 15) << 15; MARKER_BIT packet->PTS += read_bits(bitstr, 15); MARKER_BIT packet->byes_to_read = read_bits(bitstr, 15) << 15; MARKER_BIT packet->byes_to_read += read_bits(bitstr, 8); MARKER_BIT packet->intra_coded_indicator = read_bit(bitstr); packet->coding_parameters_indicator = read_bits(bitstr, 2); /*unsigned reserved2 =*/ read_bits(bitstr, 4); } return retcode; }
int main(void) { uint16_t ontime, offtime; uint8_t i,j, Loop; uint8_t region = US; // by default our code is US Loop = 0; // by default we are not going to loop TCCR1 = 0; // Turn off PWM/freq gen, should be off already TCCR0A = 0; TCCR0B = 0; i = MCUSR; // Save reset reason MCUSR = 0; // clear watchdog flag WDTCR = _BV(WDCE) | _BV(WDE); // enable WDT disable WDTCR = 0; // disable WDT while we setup DDRB = _BV(LED) | _BV(IRLED); // set the visible and IR LED pins to outputs PORTB = _BV(LED) | // visible LED is off when pin is high _BV(IRLED) | // IR LED is off when pin is high _BV(REGIONSWITCH); // Turn on pullup on region switch pin // check the reset flags if (i & _BV(BORF)) { // Brownout // Flash out an error and go to sleep flashslowLEDx(2); tvbgone_sleep(); } delay_ten_us(5000); // Let everything settle for a bit // determine region if (PINB & _BV(REGIONSWITCH)) { region = US; // US } else { region = EU; } // Tell the user what region we're in - 3 is US 4 is EU quickflashLEDx(3+region); // Starting execution loop delay_ten_us(25000); // turn on watchdog timer immediately, this protects against // a 'stuck' system by resetting it wdt_enable(WDTO_8S); // 1 second long timeout do { //Execute the code at least once. If Loop is on, execute forever. // We may have different number of codes in either database if (region == US) { j = num_NAcodes; } else { j = num_EUcodes; } // for every POWER code in our collection for(i=0 ; i < j; i++) { //To keep Watchdog from resetting in middle of code. wdt_reset(); // point to next POWER code, from the right database if (region == US) { code_ptr = (PGM_P)pgm_read_word(NApowerCodes+i); } else { code_ptr = (PGM_P)pgm_read_word(EUpowerCodes+i); } // Read the carrier frequency from the first byte of code structure const uint8_t freq = pgm_read_byte(code_ptr++); // set OCR for Timer1 to output this POWER code's carrier frequency OCR0A = freq; // Get the number of pairs, the second byte from the code struct const uint8_t numpairs = pgm_read_byte(code_ptr++); // Get the number of bits we use to index into the timer table // This is the third byte of the structure const uint8_t bitcompression = pgm_read_byte(code_ptr++); // Get pointer (address in memory) to pulse-times table // The address is 16-bits (2 byte, 1 word) const PGM_P time_ptr = (PGM_P)pgm_read_word(code_ptr); code_ptr+=2; // Transmit all codeElements for this POWER code // (a codeElement is an onTime and an offTime) // transmitting onTime means pulsing the IR emitters at the carrier // frequency for the length of time specified in onTime // transmitting offTime means no output from the IR emitters for the // length of time specified in offTime // For EACH pair in this code.... for (uint8_t k=0; k<numpairs; k++) { uint8_t ti; // Read the next 'n' bits as indicated by the compression variable // The multiply by 4 because there are 2 timing numbers per pair // and each timing number is one word long, so 4 bytes total! ti = (read_bits(bitcompression)) * 4; // read the onTime and offTime from the program memory ontime = pgm_read_word(time_ptr+ti); // read word 1 - ontime offtime = pgm_read_word(time_ptr+ti+2); // read word 2 - offtime // transmit this codeElement (ontime and offtime) xmitCodeElement(ontime, offtime, (freq!=0)); } //Flush remaining bits, so that next code starts //with a fresh set of 8 bits. bitsleft_r=0; // delay 250 milliseconds before transmitting next POWER code delay_ten_us(25000); // visible indication that a code has been output. quickflashLED(); } } while (Loop == 1); // We are done, no need for a watchdog timer anymore wdt_disable(); // flash the visible LED on PB0 4 times to indicate that we're done delay_ten_us(65500); // wait maxtime delay_ten_us(65500); // wait maxtime quickflashLEDx(4); tvbgone_sleep(); }
/*! * \brief Parse a pack header structure. * \param *bitstr The bitstream to use. * \param *pack_header A pointer to a pack_header structure. * \return 1 if succeed, 0 otherwise. * * From 'ISO/IEC 13818-1' specification: * 2.5.3.3 Pack layer of Program Stream. * Table 2-33 – Program Stream pack header */ static int parse_pack_header(Bitstream_t *bitstr, PesHeader_t *header, PackHeader_t *packet) { TRACE_INFO(MPS, BLD_GREEN "parse_pack_header()" CLR_RESET " @ %lli", header->offset_start); int retcode = SUCCESS; // Pack Headers do not have lengh field, rewind 2 bytes rewind_bits(bitstr, 16); if (read_bits(bitstr, 2) != 1) { TRACE_ERROR(MPS, "wrong 'marker_bits'"); return FAILURE; } packet->system_clock_reference_base = read_bits(bitstr, 3) << 30; MARKER_BIT packet->system_clock_reference_base += read_bits(bitstr, 15) << 15; MARKER_BIT packet->system_clock_reference_base += read_bits(bitstr, 15); MARKER_BIT packet->system_clock_reference_extension = read_bits(bitstr, 9); MARKER_BIT packet->program_mux_rate = read_bits(bitstr, 22); MARKER_BIT MARKER_BIT /*unsigned reserved =*/ read_bits(bitstr, 5); packet->pack_stuffing_length = read_bits(bitstr, 3); // Stuffing for (uint8_t i = 0; i < packet->pack_stuffing_length; i++) { if (read_bits(bitstr, 8) != 0xFF) { TRACE_ERROR(MPS, "Wrong 'stuffing_byte'"); return FAILURE; } } // System header // TODO split into its own function? if (next_bits(bitstr, 32) == 0x000001BB) { TRACE_INFO(MPS, BLD_GREEN "parse_system_header()" CLR_RESET " @ %lli", bitstream_get_absolute_byte_offset(bitstr) - 4); skip_bits(bitstr, 48); // start code + size SystemHeader_t system_header; MARKER_BIT system_header.rate_bound = read_bits(bitstr, 22); MARKER_BIT system_header.audio_bound = read_bits(bitstr, 6); system_header.fixed_flag = read_bits(bitstr, 1); system_header.CSPS_flag = read_bits(bitstr, 1); system_header.system_audio_lock_flag = read_bits(bitstr, 1); system_header.system_video_lock_flag = read_bits(bitstr, 1); MARKER_BIT system_header.video_bound = read_bits(bitstr, 5); system_header.packet_rate_restriction_flag = read_bits(bitstr, 1); /*unsigned reserved_bits =*/ read_bits(bitstr, 7); // stack it? while (next_bit(bitstr) == 1) { system_header.stream_id = read_bits(bitstr, 8); MARKER_BIT MARKER_BIT system_header.PSTD_buffer_bound_scale = read_bits(bitstr, 1); system_header.PSTD_buffer_size_bound = read_bits(bitstr, 13); } } else { TRACE_2(MPS, " > No system_header()"); } // Pack header have no length field, so we just have to parse them correctly header->offset_end = bitstream_get_absolute_byte_offset(bitstr); header->payload_length = header->offset_end - header->offset_start - 4; return retcode; }
static void read_internate_code(int* code) { char c[16] = {0}; read_bits(c, 2 * 8); sscanf(c, "%02x", code); }
// Read unsigned integer with bnum bits length. Basically an // alias for read_bits(). uint64_t u(struct bitstream *bstr, unsigned bnum) { return read_bits(bstr, bnum); }