summaryrefslogtreecommitdiff
path: root/command/streaminfo.cpp
diff options
context:
space:
mode:
authorJochen Dolze <vdr@dolze.de>2010-03-30 18:49:58 +0200
committerJochen Dolze <vdr@dolze.de>2010-03-30 18:49:58 +0200
commit74cdd9ffa1d0e5f74942051e7e22e07542929c03 (patch)
treee59472547b1ed3543b8e2d1d0e2a7c52fcb24c04 /command/streaminfo.cpp
parent6446f24dce1b30fa341b7de078ca4385d1378457 (diff)
downloadvdr-plugin-markad-74cdd9ffa1d0e5f74942051e7e22e07542929c03.tar.gz
vdr-plugin-markad-74cdd9ffa1d0e5f74942051e7e22e07542929c03.tar.bz2
Changed directory structure, added Makefiles
Diffstat (limited to 'command/streaminfo.cpp')
-rw-r--r--command/streaminfo.cpp793
1 files changed, 793 insertions, 0 deletions
diff --git a/command/streaminfo.cpp b/command/streaminfo.cpp
new file mode 100644
index 0000000..fb2bc9c
--- /dev/null
+++ b/command/streaminfo.cpp
@@ -0,0 +1,793 @@
+/*
+ * streaminfo.cpp: A program for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include "streaminfo.h"
+
+cMarkAdStreamInfo::cMarkAdStreamInfo()
+{
+ memset(&H264,0,sizeof(H264));
+ H264.frame_num=-1;
+}
+
+bool cMarkAdStreamInfo::FindAC3AudioInfos(MarkAdContext *maContext, uchar *espkt, int eslen)
+{
+#pragma pack(1)
+ struct AC3HDR
+ {
+unsigned Sync1:
+ 8;
+unsigned Sync2:
+ 8;
+unsigned CrcH:
+ 8;
+unsigned CrcL:
+ 8;
+unsigned FrameSizeIndex:
+ 6;
+unsigned SampleRateIndex:
+ 2;
+unsigned BsMod:
+ 3;
+unsigned BsID:
+ 5;
+unsigned LFE_Mix_VarField:
+ 5;
+unsigned AcMod:
+ 3;
+ };
+#pragma pack()
+ if ((!maContext) || (!espkt)) return false;
+ if (eslen<(int) sizeof(struct AC3HDR)) return false;
+
+ struct AC3HDR *ac3hdr = (struct AC3HDR *) espkt;
+
+ if ((ac3hdr->Sync1==0x0b) && (ac3hdr->Sync2==0x77))
+ {
+ // some extra checks
+ if (ac3hdr->SampleRateIndex==3) return false; // reserved
+ if (ac3hdr->FrameSizeIndex>=38) return false; // reserved
+
+ maContext->Audio.Info.Channels=0;
+ unsigned int lfe_bitmask = 0x0;
+
+ switch (ac3hdr->AcMod)
+ {
+ case 0:
+ maContext->Audio.Info.Channels=2;
+ lfe_bitmask=0x10;
+ break;
+ case 1:
+ maContext->Audio.Info.Channels=1;
+ lfe_bitmask=0x10;
+ break;
+ case 2:
+ maContext->Audio.Info.Channels=2;
+ lfe_bitmask=0x4;
+ break;
+ case 3:
+ maContext->Audio.Info.Channels=3;
+ lfe_bitmask=0x4;
+ break;
+ case 4:
+ maContext->Audio.Info.Channels=3;
+ lfe_bitmask=0x4;
+ break;
+ case 5:
+ maContext->Audio.Info.Channels=4;
+ lfe_bitmask=0x1;
+ break;
+ case 6:
+ maContext->Audio.Info.Channels=4;
+ lfe_bitmask=0x4;
+ break;
+ case 7:
+ maContext->Audio.Info.Channels=5;
+ lfe_bitmask=0x1;
+ break;
+ }
+
+ if ((ac3hdr->LFE_Mix_VarField & lfe_bitmask)==lfe_bitmask)
+ maContext->Audio.Info.Channels++;
+
+ return true;
+ }
+ return false;
+}
+
+bool cMarkAdStreamInfo::FindVideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+{
+ if ((!maContext) || (!pkt) || (!len)) return false;
+ if (!maContext->Info.VPid.Type) return false;
+
+ switch (maContext->Info.VPid.Type)
+ {
+ case MARKAD_PIDTYPE_VIDEO_H264:
+ return FindH264VideoInfos(maContext, pkt, len);
+ break;
+ case MARKAD_PIDTYPE_VIDEO_H262:
+ return FindH262VideoInfos(maContext, pkt, len);
+ break;
+ }
+ return false;
+}
+
+bool cMarkAdStreamInfo::FindH264VideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+{
+ if ((!maContext) || (!pkt) || (!len)) return false;
+
+ int nalu=pkt[4] & 0x1F;
+
+ if (nalu==NAL_AUD)
+ {
+ if (pkt[5]==0x10)
+ {
+ H264.primary_pic_typeI=true;
+ }
+ }
+
+ if (nalu==NAL_SPS)
+ {
+ uint8_t *nal_data=(uint8_t*) alloca(len);
+ if (!nal_data) return false;
+ int nal_len = nalUnescape(nal_data, pkt + 5, len - 5);
+ cBitStream bs(nal_data, nal_len);
+
+ int profile_idc, pic_order_cnt_type, i, j;
+
+ uint32_t width=0;
+ uint32_t height=0;
+ uint32_t aspect_ratio_idc=0;
+ double frame_rate=0;
+
+ profile_idc = bs.getU8(); // profile_idc
+ bs.skipBits(8); // constraint_setN_flags and reserved_zero_Nbits
+ bs.skipBits(8); // level_idc
+ bs.skipUeGolomb(); // seq_parameter_set_id
+
+ if ((profile_idc == 100) || (profile_idc == 110) || (profile_idc == 122) || (profile_idc == 244) ||
+ (profile_idc==44) || (profile_idc==83) || (profile_idc==86))
+ {
+ if (bs.getUeGolomb() == 3) // chroma_format_idc
+ bs.skipBit(); // separate_colour_plane_flag
+ bs.skipUeGolomb(); // bit_depth_luma_minus8
+ bs.skipUeGolomb(); // bit_depth_chroma_minus8
+ bs.skipBit(); // qpprime_y_zero_transform_bypass_flag
+ if (bs.getBit()) // seq_scaling_matrix_present_flag
+ {
+ for (i = 0; i < 8; ++i)
+ {
+ if (bs.getBit()) // seq_scaling_list_present_flag[i]
+ {
+ int last = 8, next = 8, size = (i < 6) ? 16 : 64;
+ for (j = 0; j < size; ++j)
+ {
+ if (next)
+ next = (last + bs.getSeGolomb()) & 0xff;
+ last = next ? next : last;
+ }
+ }
+ }
+ }
+ }
+ H264.log2_max_frame_num=bs.getUeGolomb()+4; // log2_max_frame_num_minus4
+ pic_order_cnt_type = bs.getUeGolomb(); // pic_order_cnt_type
+ if (pic_order_cnt_type == 0)
+ bs.skipUeGolomb(); // log2_max_pic_order_cnt_lsb_minus4
+ else if (pic_order_cnt_type == 1)
+ {
+ bs.skipBit(); // delta_pic_order_always_zero
+ bs.skipSeGolomb(); // offset_for_non_ref_pic
+ bs.skipSeGolomb(); // offset_for_top_to_bottom_field
+ j = bs.getUeGolomb(); // num_ref_frames_in_pic_order_cnt_cycle
+ for (i = 0; i < j; ++i)
+ bs.skipSeGolomb(); // offset_for_ref_frame[i]
+ }
+ bs.skipUeGolomb(); // max num_ref_frames
+ bs.skipBit(); // gaps_in_frame_num_value_allowed_flag
+ width = bs.getUeGolomb() + 1; // pic_width_in_mbs_minus1
+ height = bs.getUeGolomb() + 1; // pic_height_in_mbs_minus1
+ bool frame_mbs_only_flag = bs.getBit(); // frame_mbs_only_flag
+ width *= 16;
+ height *= 16 * (frame_mbs_only_flag ? 1 : 2);
+ if (!frame_mbs_only_flag)
+ bs.skipBit(); // mb_adaptive_frame_field_flag
+ bs.skipBit(); // direct_8x8_inference_flag
+ if (bs.getBit()) // frame_cropping_flag
+ {
+ uint32_t crop_left, crop_right, crop_top, crop_bottom;
+ crop_left = bs.getUeGolomb(); // frame_crop_left_offset
+ crop_right = bs.getUeGolomb(); // frame_crop_rigth_offset
+ crop_top = bs.getUeGolomb(); // frame_crop_top_offset
+ crop_bottom = bs.getUeGolomb(); // frame_crop_bottom_offset
+ width -= 2 * (crop_left + crop_right);
+ if (frame_mbs_only_flag)
+ height -= 2 * (crop_top + crop_bottom);
+ else
+ height -= 4 * (crop_top + crop_bottom);
+ }
+ // VUI parameters
+ if (bs.getBit()) // vui_parameters_present_flag
+ {
+ if (bs.getBit()) // aspect_ratio_info_present
+ {
+ aspect_ratio_idc = bs.getU8(); // aspect_ratio_idc
+ if (aspect_ratio_idc == 255) // extended sar
+ {
+ bs.skipBits(16); // sar_width
+ bs.skipBits(16); // sar_height
+ }
+ }
+ if (bs.getBit()) // overscan_info_present_flag
+ bs.skipBit(); // overscan_approriate_flag
+ if (bs.getBit()) // video_signal_type_present_flag
+ {
+ bs.skipBits(3); // video_format
+ bs.skipBit(); // video_full_range_flag
+ if (bs.getBit()) // colour_description_present_flag
+ {
+ bs.skipBits(8); // colour_primaries
+ bs.skipBits(8); // transfer_characteristics
+ bs.skipBits(8); // matrix_coefficients
+ }
+ }
+ if (bs.getBit()) // chroma_loc_info_present_flag
+ {
+ bs.skipUeGolomb(); // chroma_sample_loc_type_top_field
+ bs.skipUeGolomb(); // chroma_sample_loc_type_bottom_field
+ }
+ if (bs.getBit()) // timing_info_present_flag
+ {
+ uint32_t num_units_in_tick, time_scale;
+ num_units_in_tick = bs.getU32(); // num_units_in_tick
+ time_scale = bs.getU32(); // time_scale
+ if (num_units_in_tick > 0)
+ {
+ frame_rate = time_scale / (2*num_units_in_tick);
+ if (frame_mbs_only_flag) frame_rate/=2;
+ }
+ //bs.skipBit(); // fixed_frame_rate_flag
+ }
+ /*
+ int nal_hrd_parameters_present_flag = bs.getBit(); // nal_hrd_parameters_present_flag
+ if (nal_hrd_parameters_present_flag)
+ {
+ int cpb_cnt_minus1;
+ cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
+ bs.skipBits(4); // bit_rate_scale
+ bs.skipBits(4); // cpb_size_scale
+ for (int i = 0; i <= cpb_cnt_minus1; i++)
+ {
+ bs.skipUeGolomb(); // bit_rate_value_minus1[i]
+ bs.skipUeGolomb(); // cpb_size_value_minus1[i]
+ bs.skipBit(); // cbr_flag[i]
+ }
+ bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
+ bs.skipBits(5); // cpb_removal_delay_length_minus1
+ bs.skipBits(5); // dpb_output_delay_length_minus1
+ bs.skipBits(5); // time_offset_length
+ }
+ int vlc_hrd_parameters_present_flag = bs.getBit(); // vlc_hrd_parameters_present_flag
+ if (vlc_hrd_parameters_present_flag)
+ {
+ int cpb_cnt_minus1;
+ cpb_cnt_minus1 = bs.getUeGolomb(); // cpb_cnt_minus1
+ bs.skipBits(4); // bit_rate_scale
+ bs.skipBits(4); // cpb_size_scale
+ for (int i = 0; i <= cpb_cnt_minus1; i++)
+ {
+ bs.skipUeGolomb(); // bit_rate_value_minus1[i]
+ bs.skipUeGolomb(); // cpb_size_value_minus1[i]
+ bs.skipBit(); // cbr_flag[i]
+ }
+ bs.skipBits(5); // initial_cpb_removal_delay_length_minus1
+ bs.skipBits(5); // cpb_removal_delay_length_minus1
+ bs.skipBits(5); // dpb_output_delay_length_minus1
+ bs.skipBits(5); // time_offset_length
+ }
+ cpb_dpb_delays_present_flag = (nal_hrd_parameters_present_flag | vlc_hrd_parameters_present_flag);
+ if (cpb_dpb_delays_present_flag)
+ bs.skipBit(); // low_delay_hrd_flag
+ bs.skipBit(); // pic_struct_present_flag
+ if (bs.getBit()) // bitstream_restriction_flag
+ {
+ bs.skipBit(); // motion_vectors_over_pic_boundaries_flag
+ bs.skipUeGolomb(); // max_bytes_per_pic_denom
+ bs.skipUeGolomb(); // max_bits_per_mb_denom
+ bs.skipUeGolomb(); // log2_max_mv_length_horizontal
+ bs.skipUeGolomb(); // log2_max_mv_length_vertical
+ bs.skipUeGolomb(); // num_reorder_frames
+ bs.skipUeGolomb(); // max_dec_frame_buffering
+ }
+ */
+ }
+
+ if ((bs.getIndex() / 8)>0)
+ {
+ // set values
+ maContext->Video.Info.Interlaced=!frame_mbs_only_flag;
+ maContext->Video.Info.FramesPerSecond=frame_rate;
+ maContext->Video.Info.Width=width;
+ maContext->Video.Info.Height=height;
+
+ switch (aspect_ratio_idc)
+ {
+ case 1:
+ maContext->Video.Info.AspectRatio.Num=1;
+ maContext->Video.Info.AspectRatio.Den=1;
+
+ if (height==1080)
+ {
+ if (width==1920)
+ {
+ maContext->Video.Info.AspectRatio.Num=16;
+ maContext->Video.Info.AspectRatio.Den=9;
+ }
+ }
+
+ if (height==720)
+ {
+ if (width==960)
+ {
+ maContext->Video.Info.AspectRatio.Num=4;
+ maContext->Video.Info.AspectRatio.Den=3;
+ }
+
+ if (width==1280)
+ {
+ maContext->Video.Info.AspectRatio.Num=16;
+ maContext->Video.Info.AspectRatio.Den=9;
+ }
+ }
+ break;
+ case 2:
+ maContext->Video.Info.AspectRatio.Num=12;
+ maContext->Video.Info.AspectRatio.Den=31;
+ break;
+ case 3:
+ maContext->Video.Info.AspectRatio.Num=10;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 4:
+ maContext->Video.Info.AspectRatio.Num=16;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 5:
+ maContext->Video.Info.AspectRatio.Num=40;
+ maContext->Video.Info.AspectRatio.Den=33;
+ break;
+ case 6:
+ maContext->Video.Info.AspectRatio.Num=24;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 7:
+ maContext->Video.Info.AspectRatio.Num=20;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 8:
+ maContext->Video.Info.AspectRatio.Num=32;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 9:
+ maContext->Video.Info.AspectRatio.Num=80;
+ maContext->Video.Info.AspectRatio.Den=33;
+ break;
+ case 10:
+ maContext->Video.Info.AspectRatio.Num=18;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 11:
+ maContext->Video.Info.AspectRatio.Num=15;
+ maContext->Video.Info.AspectRatio.Den=11;
+ break;
+ case 12:
+ maContext->Video.Info.AspectRatio.Num=64;
+ maContext->Video.Info.AspectRatio.Den=33;
+ break;
+ case 13:
+ maContext->Video.Info.AspectRatio.Num=160;
+ maContext->Video.Info.AspectRatio.Den=99;
+ break;
+ case 14:
+ maContext->Video.Info.AspectRatio.Num=4;
+ maContext->Video.Info.AspectRatio.Den=3;
+ break;
+ case 15:
+ maContext->Video.Info.AspectRatio.Num=3;
+ maContext->Video.Info.AspectRatio.Den=2;
+ break;
+ case 16:
+ maContext->Video.Info.AspectRatio.Num=2;
+ maContext->Video.Info.AspectRatio.Den=1;
+ break;
+ }
+ }
+ }
+
+ if ((nalu==NAL_SLICE) || (nalu==NAL_IDR_SLICE))
+ {
+ uint8_t *nal_data=(uint8_t*) alloca(len);
+ if (!nal_data) return false;
+ int nal_len = nalUnescape(nal_data, pkt + 5, len - 5);
+ cBitStream bs(nal_data, nal_len);
+
+ bs.skipUeGolomb(); // first_mb_in_slice
+ int slice_type=bs.getUeGolomb();
+ bs.skipUeGolomb(); // pic_parameter_set_id
+ if (H264.separate_colour_plane_flag)
+ {
+ bs.skipBits(2); // colour_plane_id
+ }
+ int frame_num=bs.getBits(H264.log2_max_frame_num); // frame_num
+ if (H264.frame_num==-1) H264.frame_num=frame_num;
+
+ /*
+ if (maContext->Video.Info.Interlaced)
+ {
+ bool field_pic_flag=bs.getBit();
+ if (field_pic_flag)
+ {
+ bool bottom_field_flag=bs.getBit();
+ }
+ }
+ */
+ switch (slice_type)
+ {
+ case 0:
+ case 5:
+ slice_type=MA_P_TYPE;
+ break;
+
+ case 1:
+ case 6:
+ slice_type=MA_B_TYPE;
+ break;
+
+ case 2:
+ case 7:
+ slice_type=MA_I_TYPE;
+ break;
+
+ case 3:
+ case 8:
+ slice_type=MA_SP_TYPE;
+ break;
+
+ case 4:
+ case 9:
+ slice_type=MA_SI_TYPE;
+ break;
+
+ default:
+ break;
+ }
+
+ maContext->Video.Info.Pict_Type=slice_type;
+
+ if (!maContext->Video.Info.Interlaced)
+ {
+ if (frame_num!=H264.frame_num)
+ {
+ if (H264.primary_pic_typeI)
+ {
+ maContext->Video.Info.Pict_Type=MA_I_TYPE;
+ H264.primary_pic_typeI=false;
+ }
+ H264.frame_num=frame_num;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+const uint8_t *cMarkAdStreamInfo::nextStartCode(const uint8_t *start, const uint8_t *end)
+{
+ for (end -= 4; start < end; ++start)
+ {
+ if ((start[0] == 0x00) && (start[1] == 0x00) && (start[2] == 0x00) && (start[3] == 0x01))
+ return start;
+ }
+ return (end + 4);
+}
+
+bool cMarkAdStreamInfo::FindH262VideoInfos(MarkAdContext *maContext, uchar *pkt, int len)
+{
+ if ((!maContext) || (!pkt) || (!len)) return false;
+
+ struct H262_SequenceHdr
+ {
+unsigned Sync1:
+ 8;
+unsigned Sync2:
+ 8;
+unsigned Sync3:
+ 8;
+unsigned Sync4:
+ 8;
+unsigned WidthH:
+ 8;
+unsigned HeightH:
+ 4;
+unsigned WidthL:
+ 4;
+unsigned HeightL:
+ 8;
+unsigned FrameRateIndex:
+ 4;
+unsigned AspectRatioIndex:
+ 4;
+ };
+
+ struct H262_PictureHdr
+ {
+unsigned Sync1:
+ 8;
+unsigned Sync2:
+ 8;
+unsigned Sync3:
+ 8;
+unsigned Sync4:
+ 8;
+unsigned TemporalReferenceH:
+ 8;
+unsigned VBVDelay:
+ 3;
+unsigned CodingType:
+ 3;
+unsigned TemporalReferenceL:
+ 8;
+ };
+
+ struct H262_SequenceExt
+ {
+unsigned Sync1:
+ 8;
+unsigned Sync2:
+ 8;
+unsigned Sync3:
+ 8;
+unsigned Sync4:
+ 8;
+unsigned Profile:
+ 4;
+unsigned StartCode:
+ 4;
+unsigned WidthExtH:
+ 1;
+unsigned Chroma:
+ 2;
+unsigned Progressive:
+ 1;
+unsigned Level:
+ 4;
+unsigned BitRateExtH:
+ 5;
+unsigned HightExt:
+ 2;
+unsigned WidthExtL:
+ 1;
+unsigned Marker:
+ 1;
+unsigned BitRateExtL:
+ 7;
+ };
+
+ struct H262_SequenceExt *seqext = (struct H262_SequenceExt *) pkt;
+ struct H262_SequenceHdr *seqhdr = (struct H262_SequenceHdr *) pkt;
+ struct H262_PictureHdr *pichdr = (struct H262_PictureHdr *) pkt;
+
+ if (pichdr->Sync1==0 && pichdr->Sync2==0 && pichdr->Sync3==1 && pichdr->Sync4==0)
+ {
+ if (maContext->Video.Info.Height==0) return false;
+
+ switch (pichdr->CodingType)
+ {
+ case 1:
+ maContext->Video.Info.Pict_Type=MA_I_TYPE;
+ break;
+ case 2:
+ maContext->Video.Info.Pict_Type=MA_P_TYPE;
+ break;
+ case 3:
+ maContext->Video.Info.Pict_Type=MA_B_TYPE;
+ break;
+ case 4:
+ maContext->Video.Info.Pict_Type=MA_D_TYPE;
+ break;
+ default:
+ return false;
+ break;
+ }
+ return true;
+ }
+
+ if (seqext->Sync1==0 && seqext->Sync2==0 && seqext->Sync3==1 && seqext->Sync4==0xb5)
+ {
+ maContext->Video.Info.Interlaced=!seqext->Progressive;
+ }
+
+ if (seqhdr->Sync1==0 && seqhdr->Sync2==0 && seqhdr->Sync3==1 && seqhdr->Sync4==0xb3)
+ {
+
+ maContext->Video.Info.Height=(seqhdr->HeightH<<8)+seqhdr->HeightL;
+ maContext->Video.Info.Width=(seqhdr->WidthH<<4)+seqhdr->WidthL;
+
+ switch (seqhdr->AspectRatioIndex)
+ {
+ case 1:
+ maContext->Video.Info.AspectRatio.Num=1;
+ maContext->Video.Info.AspectRatio.Den=1;
+ break;
+ case 2:
+ maContext->Video.Info.AspectRatio.Num=4;
+ maContext->Video.Info.AspectRatio.Den=3;
+ break;
+ case 3:
+ maContext->Video.Info.AspectRatio.Num=16;
+ maContext->Video.Info.AspectRatio.Den=9;
+ break;
+ case 4:
+ maContext->Video.Info.AspectRatio.Num=11; // actually 2.21:1
+ maContext->Video.Info.AspectRatio.Den=5;
+ break;
+ default:
+ break;
+ }
+
+ switch (seqhdr->FrameRateIndex)
+ {
+ case 1:
+ maContext->Video.Info.FramesPerSecond=24000/1001; // 23.976 fps NTSC encapsulated
+ break;
+ case 2:
+ maContext->Video.Info.FramesPerSecond=24.0; // Standard international cinema film rate
+ break;
+ case 3:
+ maContext->Video.Info.FramesPerSecond=25.0; // PAL (625/50) video frame rate
+ break;
+
+ case 4:
+ maContext->Video.Info.FramesPerSecond=30000/1001; // 29.97 NTSC video frame rate
+ break;
+
+ case 5:
+ maContext->Video.Info.FramesPerSecond=30.0; // NTSC drop frame (525/60) video frame rate
+ break;
+
+ case 6:
+ maContext->Video.Info.FramesPerSecond=50.0; // double frame rate/progressive PAL
+ break;
+
+ case 7:
+ maContext->Video.Info.FramesPerSecond=60000/1001; // double frame rate NTSC
+ break;
+
+ case 8:
+ maContext->Video.Info.FramesPerSecond=60.0; // double frame rate drop-frame NTSC
+ break;
+
+ default:
+ break;
+ }
+
+ }
+ return false;
+}
+
+// taken from femon
+int cMarkAdStreamInfo::nalUnescape(uint8_t *dst, const uint8_t *src, int len)
+{
+ int s = 0, d = 0;
+
+ while (s < len)
+ {
+ if (!src[s] && !src[s + 1])
+ {
+ // hit 00 00 xx
+ dst[d] = dst[d + 1] = 0;
+ s += 2;
+ d += 2;
+ if (src[s] == 3)
+ {
+ s++; // 00 00 03 xx --> 00 00 xx
+ if (s >= len)
+ return d;
+ }
+ }
+ dst[d++] = src[s++];
+ }
+
+ return d;
+}
+
+
+cBitStream::cBitStream(const uint8_t *buf, const int len)
+ : data(buf),
+ count(len*8),
+ index(0)
+{
+}
+
+cBitStream::~cBitStream()
+{
+}
+
+int cBitStream::getBit()
+{
+ if (index >= count)
+ return (1); // -> no infinite colomb's ...
+
+ int r = (data[index >> 3] >> (7 - (index & 7))) & 1;
+ ++index;
+
+ return (r);
+}
+
+uint32_t cBitStream::getBits(uint32_t n)
+{
+ uint32_t r = 0;
+
+ while (n--)
+ r = (r | (getBit() << n));
+
+ return (r);
+}
+
+void cBitStream::skipBits(uint32_t n)
+{
+ index += n;
+}
+
+uint32_t cBitStream::getUeGolomb()
+{
+ int n = 0;
+
+ while (!getBit() && (n < 32))
+ n++;
+
+ return (n ? ((1 << n) - 1) + getBits(n) : 0);
+}
+
+int32_t cBitStream::getSeGolomb()
+{
+ uint32_t r = getUeGolomb() + 1;
+
+ return ((r & 1) ? -(r >> 1) : (r >> 1));
+}
+
+void cBitStream::skipGolomb()
+{
+ int n = 0;
+
+ while (!getBit() && (n < 32))
+ n++;
+
+ skipBits(n);
+}
+
+void cBitStream::skipUeGolomb()
+{
+ skipGolomb();
+}
+
+void cBitStream::skipSeGolomb()
+{
+ skipGolomb();
+}
+
+void cBitStream::byteAlign()
+{
+ int n = index % 8;
+
+ if (n > 0)
+ skipBits(8 - n);
+}