multiplexor.cpp

来自「Motion JPEG编解码器源代码」· C++ 代码 · 共 1,502 行 · 第 1/4 页

CPP
1,502
字号
                psstrm->NextSegment();			}			else if( master != 0 && master->SeqEndRunOut() )			{                const AUnit *nextIframe = master->NextIFrame();				if(  split_at_seq_end && nextIframe != 0)				{					runout_PTS = master->RequiredPTS(nextIframe);                    mjpeg_info( "Sequence end marker! Running out...");                    mjpeg_info("Run out PTS limit to AU %d %lld SCR=%lld",                                nextIframe->dorder,                               runout_PTS/300,                                current_SCR/300 );                    MuxStatus( LOG_INFO );					running_out = true;					seg_state = runout_segment;				}                else                {                    mjpeg_warn( "Sequence end without following I-frame!" );                }			}			break;					}		padding_packet = false;		start_of_new_pack = (packets_left_in_pack == packets_per_pack);         		for( str = estreams.begin(); str < estreams.end(); ++str )		{			(*str)->DemuxedTo(current_SCR);		}				//		// Find the ready-to-mux stream with the most urgent DTS		//		ElementaryStream *despatch = 0;		clockticks earliest = 0;		for( str = estreams.begin(); str < estreams.end(); ++str )		{#ifdef STREAM_LOGGING            mjpeg_debug("%02x: SCR=%lld (%.3f) mux=%d %d reqDTS=%lld ",                         (*str)->stream_id,                        current_SCR,                        static_cast<double>(current_SCR) /(90.0*300.0),                        (*str)->MuxPossible(current_SCR),                        (*str)->BufferSize()-(*str)->bufmodel.Space(),                        (*str)->RequiredDTS()/300                        				);#endif			if( (*str)->MuxPossible(current_SCR) && 				( !video_first || (*str)->Kind() == ElementaryStream::video )				 )			{				if( despatch == 0 || earliest > (*str)->RequiredDTS() )				{					despatch = *str;					earliest = (*str)->RequiredDTS();				}			}		}				if( underrun_ignore > 0 )			--underrun_ignore;		if( despatch )		{			despatch->BufferAndOutputSector();			video_first = false;			if( current_SCR >=  earliest && underrun_ignore == 0)			{				mjpeg_warn( "Stream %02x: data will arrive too late sent(SCR)=%lld required(DTS)=%lld", 							despatch->stream_id, 							current_SCR/300, 							earliest/300 );				MuxStatus( LOG_WARN );				// Give the stream a chance to recover				underrun_ignore = 300;				++underruns;				if( underruns > 10  )				{					mjpeg_error_exit1("Too many frame drops -exiting" );				}			}            if( despatch->nsec > 50 &&                despatch->Lookahead( ) != 0 && ! running_out)                despatch->UpdateBufferMinMax();			padding_packet = false;		}		else		{            //            // If we got here no stream could be muxed out.            // We therefore generate padding packets if necessary            // usually this is because reciever buffers are likely to be            // full.              //            if( vbr )            {                //                // VBR: For efficiency we bump SCR up to five times or                // until it looks like buffer status will change                NextPosAndSCR();                clockticks next_change = static_cast<clockticks>(0);                for( str = estreams.begin(); str < estreams.end(); ++str )                {                    clockticks change_time = (*str)->bufmodel.NextChange();                    if( next_change == 0 || change_time < next_change )                    {                        next_change = change_time;                    }                }                unsigned int bumps = 5;                while( bumps > 0                        && next_change > current_SCR + ticks_per_sector)                {                    NextPosAndSCR();                    --bumps;                }                                        }            else            {                // Just output a padding packet                OutputPadding (	false);            }			padding_packet = true;		}		/* Update the counter for pack packets.  VBR is a tricky 		   case as here padding packets are "virtual" */				if( ! (vbr && padding_packet) )		{			--packets_left_in_pack;			if (packets_left_in_pack == 0) 				packets_left_in_pack = packets_per_pack;		}		MuxStatus( LOG_DEBUG );		/* Unless sys headers are always required we turn them off after the first		   packet has been generated */		include_sys_header = always_sys_header_in_pack;		pcomp = completed.begin();		str = estreams.begin();		while( str < estreams.end() )		{			if( !(*pcomp) && (*str)->MuxCompleted() )			{				mjpeg_info( "STREAM %02x completed @ frame %d.", (*str)->stream_id, (*str)->DecodeOrder() );				MuxStatus( LOG_DEBUG );				(*pcomp) = true;			}			++str;			++pcomp;		}	}	// Tidy up		OutputSuffix( );	psstrm->Close();	mjpeg_info( "Multiplex completion at SCR=%lld.", current_SCR/300);	MuxStatus( LOG_INFO );	for( str = estreams.begin(); str < estreams.end(); ++str )	{		(*str)->Close();        if( (*str)->nsec <= 50 )            mjpeg_info( "BUFFERING stream too short for useful statistics");        else            mjpeg_info( "BUFFERING min %d Buf max %d",                        (*str)->BufferMin(),                        (*str)->BufferMax()                 );	}    if( underruns> 0 )	{		mjpeg_error_exit1( "MUX STATUS: Frame data under-runs detected!" );	}	else	{		mjpeg_info( "MUX STATUS: no under-runs detected.");	}}/**   Calculate the packet payload of the output stream at a certain timestamp. @param strm the output stream@param buffers the number of buffers@param PTSstamp presentation time stamp@param DTSstamp decoding time stamp */unsigned int Multiplexor::PacketPayload( MuxStream &strm, bool buffers, 										  bool PTSstamp, bool DTSstamp ){	return psstrm->PacketPayload( strm, sys_header_ptr, pack_header_ptr, 								  buffers, 								  PTSstamp, DTSstamp)        - strm.StreamHeaderSize();}/***************************************************  WritePacket - Write out a normal packet carrying data from one of              the elementary stream being muxed.@param max_packet_data_size the maximum packet data size allowed@param strm output mux stream@param buffers ?@param PTSstamp presentation time stamp of the packet@param DTSstamp decoding time stamp of the packet@param timestamps ?@param returns the written bytes/packets (?)***************************************************/unsigned int Multiplexor::WritePacket( unsigned int     max_packet_data_size,                           MuxStream        &strm,                           bool 	 buffers,                           clockticks   	 PTS,                           clockticks   	 DTS,                           uint8_t 	 timestamps	){    unsigned int written =        psstrm->CreateSector ( pack_header_ptr,                               sys_header_ptr,                               max_packet_data_size,                               strm,                               buffers,                               false,                               PTS,                               DTS,                               timestamps );    NextPosAndSCR();    return written;}/*************************************************** * * WriteRawSector - Write out a packet carrying data for *                    a control packet with irregular content.@param rawsector data for the raw sector@param length length of the raw sector ***************************************************/voidMultiplexor::WriteRawSector(  uint8_t *rawsector,                               unsigned int     length	){    //    // Writing raw sectors when packs stretch over multiple sectors    // is a recipe for disaster!    //    assert( packets_per_pack == 1 );	psstrm->RawWrite( rawsector, length );	NextPosAndSCR();}/******************************************************************	OutputPadding	generates Pack/Sys Header/Packet information for a 	padding stream and saves the sector	We have to pass in a special flag to cope with appalling mess VCD	makes of audio packets (the last 20 bytes being dropped thing) 0 =	Fill the packet completetely.  This include "audio packets" that    include no actual audio, only a system header and padding.@param vcd_audio_pad flag for VCD audio padding******************************************************************/void Multiplexor::OutputPadding (bool vcd_audio_pad){    if( vcd_audio_pad )        psstrm->CreateSector ( pack_header_ptr, sys_header_ptr,                               0,                               vcdapstrm,                               false, false,                               0, 0,                               TIMESTAMPBITS_NO );    else        psstrm->CreateSector ( pack_header_ptr, sys_header_ptr,                               0,                               pstrm,                               false, false,                               0, 0,                               TIMESTAMPBITS_NO );    ++pstrm.nsec;	NextPosAndSCR();} /****************************************************************** *	OutputGOPControlSector *  DVD System headers are carried in peculiar sectors carrying 2 *  PrivateStream2 packets.   We're sticking 0's in the packets *  as we have no idea what's supposed to be in there. * * Thanks to Brent Byeler who worked out this work-around. * ******************************************************************/void Multiplexor::OutputDVDPriv2 (	){    uint8_t *packet_size_field;    uint8_t *index;    uint8_t *sector_buf = new uint8_t[sector_size];    unsigned int tozero;    assert( sector_size == 2048 );    PS_Stream::BufferSectorHeader( sector_buf,                                pack_header_ptr,                                &sys_header,                                index );    PS_Stream::BufferPacketHeader( index,                                   PRIVATE_STR_2,                                   2,      // MPEG 2                                   false,  // No buffers                                   0,                                   0,                                   0,      // No timestamps                                   0,                                   TIMESTAMPBITS_NO,                                   0, // Natural PES header length                                   packet_size_field,                                   index );    tozero = sector_buf+1024-index;    memset( index, 0, tozero);    index += tozero;    PS_Stream::BufferPacketSize( packet_size_field, index );        PS_Stream::BufferPacketHeader( index,                                   PRIVATE_STR_2,                                   2,      // MPEG 2                                   false,  // No buffers                                   0,                                   0,                                   0,      // No timestamps                                   0,                                   TIMESTAMPBITS_NO,                                   0, // Natural PES header length                                   packet_size_field,                                   index );    tozero = sector_buf+2048-index;    memset( index, 0, tozero );    index += tozero;    PS_Stream::BufferPacketSize( packet_size_field, index );    WriteRawSector( sector_buf, sector_size );	delete [] sector_buf;}/*  * Local variables: *  c-file-style: "stroustrup" *  tab-width: 4 *  indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

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