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 + -
显示快捷键?