⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 h264.cpp

📁 linux下实现视频播放的播放器
💻 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 + -