📄 h264.cpp
字号:
/* * Copyright (C) 2007 gulikoza * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* $Id$ */#include "iptv.h"#include "h264.h"//#define DEBUG#define MODULE "h264"#include "log.h"class h264reader{private: int bits; int size; int read; unsigned char * pkt;public: h264reader(unsigned char * p, int offset, int s):bits(8),size(s-offset),read(0) { pkt = p+offset; DEBUG_MSG("Starting bytes: 0x%x 0x%x 0x%x", pkt[0], pkt[1], pkt[2]); } unsigned int GetBits(int num) { if(num == 0) { LOG_MSG("Requested 0 bits"); return 0; } if(num > 32) { LOG_MSG("Requested too many (%d) bits", num); return 0; } if(bits == 0) { if(size == 0) { LOG_MSG("Unexpected end of packet!"); return 0; } bits = 8; size--; pkt++; read++; // Emulation prevention byte if((pkt[0] == 0x3) && (read > 2) && (pkt[-1] == 0x0) && (pkt[-2] == 0x0)) { size--; pkt++; } } int use = (num>bits) ? bits:num; // Get bits from current byte unsigned int ret = (pkt[0]>>(bits-use)) & ((0x1<<use)-1); bits -= use; DEBUG_MSG("Bits to be used: %d, value 0x%x", use, ret); if(num-use == 0) return ret; return ((ret<<(num-use))|GetBits(num-use)); } unsigned int Get_UEG() { int bits = 0; while(GetBits(1) == 0) bits++; DEBUG_MSG("Exp-Golomb length: %d", bits); if(bits == 0) return 0; unsigned int ret = ((0x1<<bits)|GetBits(bits))-1; DEBUG_MSG("Exp-Golomb read: %d", ret); return ret; } int Get_SEG() { int num = Get_UEG(); if(num == 0) return num; if(num % 2 == 0) num = num / (-2); else num = (num + 1) / 2; DEBUG_MSG("Signed Exp-Golomb returned %d", num); return num; }};int h264findnal_type(unsigned char * pkt, unsigned int size, int type){ unsigned int ndx = 0; while(ndx < (size - 3)) { if(pkt[ndx] < 0x2) { if((pkt[ndx] == 0x1) && (ndx > 2)) ndx -= 3; else if((pkt[ndx+1] == 0x1) && (ndx > 1)) ndx -= 2; else if((pkt[ndx+2] == 0x1) && (ndx > 0)) ndx -= 1; unsigned int nal = pkt[ndx]<<24 | pkt[ndx+1]<<16 | pkt[ndx+2]<<8 | pkt[ndx+3]; if(nal != 0x1) { ndx += 4; continue; } // NAL starts after the separator ndx += 4; if(pkt[ndx]&0x80) { ndx += 4; LOG_MSG("Forbidden NAL bit set!"); continue; } int t = (pkt[ndx]&0x1F); LOG_MSG("Found NAL unit: ID 0x%x, type 0x%x @ %d", (pkt[ndx]&0x60)>>5, t, ndx); if(t == type) return ndx+1; } ndx += 4; } return -1;}// Sequence parameter set is in NAL unit type 0x7int h264parse_seq(h264info * info){ h264reader * stream = new h264reader(info->pkt, info->offset, info->size); int profile_idc = stream->GetBits(8); LOG_MSG("Profile_idc: %d", profile_idc); // Skip constraint... stream->GetBits(16); // Seq_id stream->Get_UEG(); // High-profile has additional info? if(profile_idc >= 100) { if(stream->Get_UEG() == 3) // chroma_format_idc stream->GetBits(1); // residual_color_transform_flag stream->Get_UEG(); // bit_depth_luma_minus8 stream->Get_UEG(); // bit_depth_chroma_minus8 stream->GetBits(1); // Scaling matrix if(stream->GetBits(1)) { LOG_MSG("Scaling matrix is present"); for(unsigned int i = 0; i < 8; i++) { if(stream->GetBits(1)) { int next = 8, last = 8; for(unsigned int j = (i>6 ? 64:16); j; j--) { if(next) next = (last + stream->Get_SEG()) & 0xff; last = next ? next : last; } } } } } // log2_max_frame_num_minus4 stream->Get_UEG(); // pic_order_cnt_type profile_idc = stream->Get_UEG(); if(profile_idc == 0) { LOG_MSG("Pic_order_cnt_type == 0"); stream->Get_UEG(); } else if(profile_idc == 1) { LOG_MSG("Pic_order_cnt_type == 1"); stream->GetBits(1); stream->Get_UEG(); stream->Get_UEG(); for(unsigned int i = stream->Get_UEG(); i; i--) stream->Get_UEG(); } stream->Get_UEG(); stream->GetBits(1); // Finally what we want... info->width = (stream->Get_UEG() + 1) * 16; info->height = (stream->Get_UEG() + 1) * 16; if(!stream->GetBits(1)) { // Interlaced... info->height *= 2; stream->GetBits(1); } LOG_MSG("Got picture parameters: %dx%d", info->width, info->height); stream->GetBits(1); if(stream->GetBits(1)) { stream->Get_UEG(); stream->Get_UEG(); stream->Get_UEG(); stream->Get_UEG(); } // Hopefully VUI is also present... info->aspect = 0.0; info->frame_time = 0.0; if(stream->GetBits(1)) { if(stream->GetBits(1)) { switch(stream->GetBits(8)) { case 1: info->aspect = 1.0; break; case 2: info->aspect = 12.0/11.0; break; case 3: info->aspect = 10.0/11.0; break; case 4: info->aspect = 16.0/11.0; break; case 5: info->aspect = 40.0/33.0; break; case 6: info->aspect = 24.0/11.0; break; case 7: info->aspect = 20.0/11.0; break; case 8: info->aspect = 32.0/11.0; break; case 9: info->aspect = 80.0/33.0; break; case 10: info->aspect = 18.0/11.0; break; case 11: info->aspect = 15.0/11.0; break; case 12: info->aspect = 64.0/33.0; break; case 13: info->aspect = 160.0/99.0; break; case 255: info->aspect = (double)stream->GetBits(16); info->aspect /= (double)stream->GetBits(16); break; default: LOG_MSG("AR not specified!"); } } LOG_MSG("VUI parameters present, AR: %.2f", info->aspect); // Overscan if(stream->GetBits(1)) stream->GetBits(1); // Video info if(stream->GetBits(1)) { stream->GetBits(3); stream->GetBits(1); if(stream->GetBits(1)) { stream->GetBits(8); stream->GetBits(8); stream->GetBits(8); } } if(stream->GetBits(1)) { stream->Get_UEG(); stream->Get_UEG(); } if(stream->GetBits(1)) { info->frame_time = stream->GetBits(32) * 2000; info->frame_time /= stream->GetBits(32); LOG_MSG("Timing info present: %.2f", info->frame_time); } } // Already done? :-) delete stream; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -