#define DEMUXER_H264_ACCESS_UNIT 0x00000109
#define DEMUXER_H264_SEQ_PARAMETER_SET 0x00000107
#define DEMUXER_H264_SUB_ENHANCEMENT_INF 0x00000106
-
+#define DEMUXER_H264_CODED_SLICE_IDR 0x00000105
+#define DEMUXER_H264_CODED_SLICE_NON_IDR 0x00000101
#define SEEK_THRESHOLD 150000 // About 1.5 seconds
UINT getUe();
int getSe();
bool isEonalu() {return eonalu;};
+ int getPos(){return pos;};
protected:
UCHAR* nalu_buf;
}
}
-UINT PESPacket::countPictureHeaders(bool h264) const
+UINT PESPacket::countPictureHeaders(bool h264, struct PictCountInfo& pinfo) const
{
if (size < 12) return 0;
UINT pattern = ( ((UINT)data[ 8] << 24) |
UINT pos = 11;
UINT count=0;
if (h264) {
-
+ //inspired by vdr algorithm for frame couting by Klaus Schmidinger
while (pos<size)
{
pos++;
pattern = (pattern << 8) | data[pos];
- if (pattern==DEMUXER_H264_ACCESS_UNIT) count++;
+ if ((pattern &0xFFFFFF00)==0x00000100) {
+ UINT testpattern=(pattern& 0xFFFFFF1f);
+ if (testpattern==DEMUXER_H264_ACCESS_UNIT) pinfo.hasaccessunit=true;
+ else if (testpattern==DEMUXER_H264_SEQ_PARAMETER_SET ) {
+ pinfo.hassps=true;
+ NALUUnit nalu(data+pos-3,getSize()-pos+3);
+ int profile=nalu.getBits(8);
+ nalu.getBits(8); //constraints
+ nalu.getBits(8); //level_idc
+ nalu.getUe(); //seq_parameter_set_id
+ int chroma=1;
+ pinfo.separate_color_plane_flag=0;
+ if (profile==100 || profile==110 || profile==122 || profile==144)
+ {
+ chroma=nalu.getUe();
+ if (chroma==3)
+ {
+ pinfo.separate_color_plane_flag=nalu.getBits(1);
+ }
+ nalu.getUe(); //bit depth lume
+ nalu.getUe(); //bit depth chrome
+ nalu.getBits(1);
+ if (nalu.getBits(1))
+ {
+ for (int i=0;i<8;i++){
+ if (nalu.getBits(1))
+ {
+ if (i<6)
+ {
+ UINT lastscale=8;
+ UINT nextscale=8;
+ for (int j=0;j<16;j++) {
+ if (nextscale!=0) {
+ UINT delta=nalu.getSe();
+ nextscale=(lastscale+delta+256)%256;
+ }
+ lastscale=(nextscale==0)?lastscale:nextscale;
+ }
+ }
+ else
+ {
+ UINT lastscale=8;
+ UINT nextscale=8;
+ for (int j=0;j<64;j++) {
+ if (nextscale!=0) {
+ UINT delta=nalu.getSe();
+ nextscale=(lastscale+delta+256)%256;
+ }
+ lastscale=(nextscale==0)?lastscale:nextscale;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ pinfo.log2_max_frame_num=nalu.getUe()+4; //log2framenum
+ UINT temp=nalu.getUe();
+ if (temp==0) //pict order
+ nalu.getUe();
+ else if (temp==1) {
+ nalu.getBits(1);
+ nalu.getSe();
+ nalu.getSe();
+ UINT temp2=nalu.getUe();
+ for (int i=0;i<temp2;i++)
+ nalu.getSe();
+ }
+ nalu.getUe(); //Num refframes
+ nalu.getBits(1);
+ nalu.getUe();
+ nalu.getUe();
+ pinfo.frame_mbs_only_flag=nalu.getBits(1);
+ pattern=0xFFFFFF;
+ pos+=nalu.getPos();
+
+ } if (testpattern==DEMUXER_H264_CODED_SLICE_IDR || testpattern==DEMUXER_H264_CODED_SLICE_NON_IDR ) {
+ /* Log::getInstance()->log("Demuxer", Log::ERR,
+ "Has slice %d %d %d %d %d",pinfo.hasaccessunit, pinfo.hassps,pinfo.frame_mbs_only_flag,pinfo.separate_color_plane_flag,
+ pinfo.log2_max_frame_num);*/
+ if (pinfo.hasaccessunit && pinfo.hassps) {
+
+ NALUUnit nalu(data+pos-3,getSize()-pos+3);
+ nalu.getUe();// first_mb_in_slice
+ nalu.getUe();//sliectype
+ if (!pinfo.frame_mbs_only_flag) {
+ nalu.getUe(); //pic_paramter_set_id
+ if (pinfo.separate_color_plane_flag) nalu.getBits(2);
+ nalu.getBits(pinfo.log2_max_frame_num);
+ //if (!frame_mbs_only_flag)
+ if (nalu.getBits(1)) { //field_picture
+ if (!nalu.getBits(1)) { //bottom_field
+ count++;
+ }
+ } else count++;
+
+ } else count++;
+ pattern=0xFFFFFF;
+ pos+=nalu.getPos();
+ pinfo.hasaccessunit=false;
+ }
+ }
+ }
}
return count;
} else {