zalphastrm_in.cpp

来自「Motion JPEG编解码器源代码」· C++ 代码 · 共 493 行

CPP
493
字号
/* *  zalphastrm_in.cpp:  Members of Z/Alpha stream class related to raw stream *               scanning and buffering. * *  Copyright (C) 2001 Gernot Ziegler <gz@lysator.liu.se> *  Copyright (C) 2001 Andrew Stevens <andrew.stevens@philips.com> * * *  This program is free software; you can redistribute it and/or *  modify it under the terms of version 2 of the GNU General Public License *  as published by the Free Software Foundation. * *  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. */#include <config.h>#include <math.h>#include <stdlib.h>#include "zalphastrm.hpp"#include "interact.hpp"#include "multiplexor.hpp"static void marker_bit (IBitStream &bs, unsigned int what){    if (what != bs.Get1Bit())    {        mjpeg_error ("Illegal MPEG stream at offset (bits) %lld: supposed marker bit not found.",bs.bitcount());        exit (1);    }}void ZAlphaStream::ScanFirstSeqHeader(){    if (bs.GetBits( 32)==ZA_SEQUENCE_HEADER)    {        mjpeg_debug("Reading Z/Alpha sequence header ... ");		num_sequence++;                int headerlen = bs.GetBits(16);        mjpeg_info("Header frame length is %d", headerlen);        int frame_num = bs.GetBits(8);        mjpeg_info("Header frame number is %d", frame_num);		horizontal_size	= bs.GetBits( 12);		vertical_size	= bs.GetBits( 12);#if 0 		aspect_ratio	= bs.GetBits(  4);		picture_rate 	= bs.GetBits(  4);		bit_rate		= bs.GetBits( 18);		marker_bit( bs, 1);		vbv_buffer_size	= bs.GetBits( 10);		CSPF		= bs.get1bit();#else        // hardcoded here, but should really be copied from the video stream... 		aspect_ratio	= 2;		picture_rate	= 3;		bit_rate		= 3000;        //bit_rate = 0x3ffff;		//marker_bit( bs, 1);		vbv_buffer_size	= 50;		CSPF		= 0;#endif        uint8_t conv[4];        conv[0] = bs.GetBits(8);        conv[1] = bs.GetBits(8);        conv[2] = bs.GetBits(8);        conv[3] = bs.GetBits(8);        memcpy(&z_min, conv, 4);        conv[0] = bs.GetBits(8);        conv[1] = bs.GetBits(8);        conv[2] = bs.GetBits(8);        conv[3] = bs.GetBits(8);        memcpy(&z_max, conv, 4);        z_format = bs.GetBits(8);        printf("Z format byte is set to 0x%x\n", z_format);        z_depth = bs.GetBits(8);        alpha_depth = bs.GetBits(8);    }     else    {		mjpeg_error ("Invalid MPEG ZAlpha stream header.");		exit (1);    }	if (mpeg_valid_framerate_code(picture_rate))    {		frame_rate = Y4M_RATIO_DBL(mpeg_framerate(picture_rate));	}    else    {		frame_rate = 25.0;	}}void ZAlphaStream::Init ( const int stream_num ){	mjpeg_debug( "SETTING video buffer to %d", parms->DecodeBufferSize() );	MuxStream::Init( ZALPHA_STR_0+stream_num,					 1,  // Buffer scale					 parms->DecodeBufferSize()*1024,					 0,  // Zero stuffing					 muxinto.buffers_in_video,					 muxinto.always_buffers_in_video);    mjpeg_debug( "Scanning for header info: Z/Alpha stream %02x (%s)",                ZALPHA_STR_0+stream_num,                bs.StreamName()                );	InitAUbuffer();	SetBufSize( 4*1024*1024 );	ScanFirstSeqHeader();	/* Skip to the end of the 1st AU (*2nd* Picture start!)	*/	AU_hdr = ZA_SEQUENCE_HEADER;	AU_pict_data = 1;	AU_start = 0LL;        OutputSeqhdrInfo();}//// Set the Maximum STD buffer delay for this video stream.// By default we set 1 second but if we have specified a video// buffer that can hold more than 1.0 seconds demuxed data we// set the delay to the time to fill the buffer.//void ZAlphaStream::SetMaxStdBufferDelay( unsigned int dmux_rate ){    double max_delay = CLOCKS;    if( static_cast<double>(BufferSize()) / dmux_rate > 1.0 )        max_delay *= static_cast<double>(BufferSize()) / dmux_rate;    //    // To enforce a maximum STD buffer residency the    // calculation is a bit tricky as when we decide to mux we may    // (but not always) have some of the *previous* picture left to    // mux in which case it is the timestamp of the next picture that counts.    // For simplicity we simply reduce the limit by 1.5 frame intervals    // and use the timestamp for the current picture.    //    if( frame_rate > 10.0 )        max_STD_buffer_delay = static_cast<clockticks>(max_delay * (frame_rate-1.5)/frame_rate);    else        max_STD_buffer_delay = static_cast<clockticks>(10.0 * max_delay / frame_rate);    mjpeg_error_exit1("dmux_rate is %d max_delay %g", dmux_rate, max_delay);}//// Return whether AU buffer needs refilling.  There are two cases:// 1. We have less than our look-ahead "FRAME_CHUNK" buffer AU's// buffered 2. AU's are very small and we could have less than 1// sector's worth of data buffered.//bool ZAlphaStream::AUBufferNeedsRefill(){    int retval =         !eoscan        && ( aunits.current()+FRAME_CHUNK > last_buffered_AU             ||             bs.BufferedBytes() < muxinto.sector_size             );    //mjpeg_info("Z/A needs %s refill.\n", retval ? "a":"no");    return retval;}//// Refill the AU unit buffer setting  AU PTS DTS from the scanned// header information...//void ZAlphaStream::FillAUbuffer(unsigned int frames_to_buffer){    int frame_num;    unsigned int bits_persec;    int headerlen;    if( eoscan )        return;	last_buffered_AU += frames_to_buffer;	mjpeg_debug( "Scanning %d Z/A video frames to frame %d", 				 frames_to_buffer, last_buffered_AU );    // We set a limit of 2M to seek before we give up.    // This is intentionally very high because some heavily    // padded still frames may have a loooong gap before    // a following sequence end marker.	while(!bs.eos()           && decoding_order < last_buffered_AU           && !muxinto.AfterMaxPTS(access_unit.PTS)          && bs.SeekSync( SYNCWORD_START, 24, 2*1024*1024)		)	{		syncword = (SYNCWORD_START<<8) + bs.GetBits( 8);        //mjpeg_info( "Traversing ... syncword 0x%x ", syncword); 		if( AU_pict_data )		{						/* Handle the header *ending* an AU...			   If we have the AU picture data an AU and have now			   reached a header marking the end of an AU fill in the			   the AU length and append it to the list of AU's and			   start a new AU.  I.e. sequence and gop headers count as			   part of the AU of the corresponding picture			*/			stream_length = bs.bitcount()-32LL;			switch (syncword) 			{            // note: there are currently _no_ sequence distinctions in Z/Alpha ! 			case ZA_SEQUENCE_HEADER :				access_unit.start = AU_start;				access_unit.length = (int) (stream_length - AU_start)>>3;				access_unit.end_seq = 0;                access_unit.type = IFRAME;				avg_frames[access_unit.type-1]+=access_unit.length;                access_unit.dorder = decoding_order;                access_unit.seq_header = 1; //( AU_hdr == SEQUENCE_HEADER);                                bits_persec = 					(unsigned int) ( ((double)(stream_length - prev_offset)) *									 2*frame_rate / ((double)(2 /*+ fields_presented- group_start_field*/)));				                //mjpeg_info("New bits_persec is %d bits/second.", bits_persec);                				if( bits_persec > max_bits_persec )				{					max_bits_persec = bits_persec;				}				prev_offset = stream_length;                headerlen = bs.GetBits(16);                frame_num = bs.GetBits(8);                //mjpeg_info("Header frame number is %d", frame_num);				mjpeg_debug( "Found Z/Alpha AU %d (real: %d): DTS=%d", access_unit.dorder, frame_num,							 access_unit.DTS/300);                                if ( decoding_order >= old_frames+1000 )                {                    mjpeg_debug("Got %d picture headers.", decoding_order);                    old_frames = decoding_order;                }                decoding_order++;                //mjpeg_info("Decoding order is now %d", decoding_order);                NextDTSPTS( access_unit.DTS, access_unit.PTS);				aunits.append( access_unit ); // INSERTING NEW AUNIT !                                 if ((access_unit.type>0) && (access_unit.type<5))                {                    num_frames[access_unit.type-1]++; // counts the frames in this Z/Alpha stream                }                                				AU_hdr = syncword;				AU_start = stream_length;				AU_pict_data = 1;                if (decoding_order >= last_buffered_AU)                {                    mjpeg_debug("Reached end of buffer ...");                    break;                }				break;			case SEQUENCE_END: // still using the MPEG sequence end, so that we don't have to use another SYNCWORD				access_unit.start = AU_start;				access_unit.length = (int) ((stream_length - AU_start)>>3)+4;				access_unit.end_seq = 1;				avg_frames[access_unit.type-1]+=access_unit.length;                access_unit.dorder = decoding_order;                access_unit.seq_header = 1; //( AU_hdr == SEQUENCE_HEADER);                access_unit.type = IFRAME;				mjpeg_debug( "Adding final AU %d (real: %d): DTS=%d", access_unit.dorder, frame_num,							 access_unit.DTS/300);                NextDTSPTS( access_unit.DTS, access_unit.PTS);				aunits.append( access_unit ); // INSERTING NEW AUNIT ! 				//access_unit.length = ((stream_length - AU_start)>>3)+4;				//access_unit.end_seq = 1;				//aunits.append( access_unit );				mjpeg_debug( "Z/Alpha: Scanned to end AU %d at %d", access_unit.dorder, stream_length/8 );				avg_frames[access_unit.type-1]+=access_unit.length;				/* Do we have a sequence split in the video stream? */				if( !bs.eos() && 					bs.GetBits( 32) ==SEQUENCE_HEADER )				{					stream_length = bs.bitcount()-32LL;					AU_start = stream_length;					syncword  = AU_hdr = SEQUENCE_HEADER;					AU_pict_data = 0;					if( !muxinto.split_at_seq_end )						mjpeg_warn("Sequence end marker found in video stream but single-segment splitting specified!" );				}				else				{					if( !bs.eos() && muxinto.split_at_seq_end )						mjpeg_warn("No seq. header starting new sequence after seq. end!");				}									num_seq_end++;				break;			}		}	}	last_buffered_AU = decoding_order;	num_pictures = decoding_order;		eoscan = bs.eos() || muxinto.AfterMaxPTS(access_unit.PTS);}void ZAlphaStream::Close(){    unsigned int comp_bit_rate	;    unsigned int peak_bit_rate  ;    stream_length = (unsigned int)(bs.bitcount() / 8);    for (int i=0; i<4; i++)	{		avg_frames[i] /= num_frames[i] == 0 ? 1 : num_frames[i];	}    comp_bit_rate = (unsigned int)		(			(((double)stream_length) / ((double)fields_presented)) * 2.0			* ((double)frame_rate)  + 25.0			) / 50;		/* Peak bit rate in 50B/sec units... */	peak_bit_rate = ((max_bits_persec / 8) / 50);	mjpeg_info ("VIDEO_STATISTICS: %02x", stream_id);     mjpeg_info ("Video Stream length: %11llu bytes",stream_length);    mjpeg_info ("Sequence headers: %8u",num_sequence);    mjpeg_info ("Sequence ends   : %8u",num_seq_end);    mjpeg_info ("No. Pictures    : %8u",num_pictures);    mjpeg_info ("No. I Frames    : %8u avg. size%6u bytes",			  num_frames[0],avg_frames[0]);    mjpeg_info("Average bit-rate : %8u bits/sec",comp_bit_rate*400);    mjpeg_info("Peak bit-rate    : %8u  bits/sec",peak_bit_rate*400);	}	/*************************************************************************	OutputSeqHdrInfo     Display sequence header parameters*************************************************************************/void ZAlphaStream::OutputSeqhdrInfo (){	const char *str;	mjpeg_info("Z/Alpha STREAM: %02x", stream_id);    mjpeg_info ("Frame width     : %u\n",horizontal_size);    mjpeg_info ("Frame height    : %u\n",vertical_size);    mjpeg_info ("Z min    : %f\n", z_min);    mjpeg_info ("Z max    : %f\n", z_max);    mjpeg_info ("Z format 0x%x, depth    : %d", z_format, z_depth);    mjpeg_info ("Alpha depth   : %d", alpha_depth);	if (mpeg_valid_aspect_code(muxinto.mpeg, aspect_ratio))		str =  mpeg_aspect_code_definition(muxinto.mpeg,aspect_ratio);	else		str = "forbidden";    mjpeg_info ("Aspect ratio    : %s", str );    if (picture_rate == 0)		mjpeg_info( "Picture rate    : forbidden");    else if (mpeg_valid_framerate_code(picture_rate))		mjpeg_info( "Picture rate    : %2.3f frames/sec",					Y4M_RATIO_DBL(mpeg_framerate(picture_rate)) );    else		mjpeg_info( "Picture rate    : %x reserved",picture_rate);				    if (bit_rate == 0x3ffff)		{			bit_rate = 0;			mjpeg_info( "Bit rate        : variable"); 		}    else if (bit_rate == 0)		mjpeg_info( "Bit rate       : forbidden");    else		mjpeg_info( "Bit rate        : %u bits/sec",					bit_rate*400);    mjpeg_info("Vbv buffer size : %u bytes",vbv_buffer_size*2048);    mjpeg_info("CSPF            : %u",CSPF);}//// Compute DTS of current AU in the Z/alpha sequence being// scanned.  //void ZAlphaStream::NextDTSPTS( clockticks &DTS, clockticks &PTS){#if 0  // ZAlpha can't currently handle interlaced or 3:2 pulldown    if( pict_struct != PIC_FRAME )    {		DTS = static_cast<clockticks>			(fields_presented * (double)(CLOCKS/2) / frame_rate);        int dts_fields = temporal_reference*2 + group_start_field+1;        if( temporal_reference == prev_temp_ref )            dts_fields += 1;        PTS =            static_cast<clockticks>(dts_fields* (double)(CLOCKS/2) / frame_rate);		access_unit.porder = temporal_reference /*+ group_start_pic*/;        fields_presented += 1;    }	    else if( pulldown_32 )	{		int frames2field;		int frames3field;		DTS = static_cast<clockticks>			(fields_presented * (double)(CLOCKS/2) / frame_rate);		if( repeat_first_field )		{			frames2field = (temporal_reference+1) / 2;			frames3field = temporal_reference / 2;			fields_presented += 3;		}		else		{			frames2field = (temporal_reference) / 2;			frames3field = (temporal_reference+1) / 2;			fields_presented += 2;		}		PTS = static_cast<clockticks>			((frames2field*2 + frames3field*3 + group_start_field+1) * (double)(CLOCKS/2) / frame_rate);		access_unit.porder = temporal_reference + group_start_pic;	}    else#endif	{		DTS = static_cast<clockticks> 			(decoding_order * (double)CLOCKS / frame_rate);        PTS=DTS;		fields_presented += 2;	}}/*  * Local variables: *  c-file-style: "stroustrup" *  tab-width: 4 *  indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?