📄 systems.cpp
字号:
/* * systems.cpp: Program/System stream packet generator * * * 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/param.h>#include "systems.hpp"#include "mplexconsts.hpp"PS_Stream:: PS_Stream( unsigned _mpeg, unsigned int _sector_size, OutputStream &_output_strm, off_t max_seg_size ) : mpeg_version( _mpeg), sector_size( _sector_size ), output_strm(_output_strm ), max_segment_size( max_seg_size ){ sector_buf = new uint8_t[sector_size]; max_segment_size = max_seg_size;}PS_Stream::~PS_Stream(){ delete [] sector_buf;}boolPS_Stream::SegmentLimReached(){ off_t written = output_strm.SegmentSize(); return max_segment_size != 0 && written > max_segment_size;}/************************************************************** Packet payload compute how much payload a sector-sized packet with the specified headers can carry... TODO: Should really be called "Sector Payload"**************************************************************/ unsigned int PS_Stream::PacketPayload( MuxStream &mux_strm, Sys_header_struc *sys_header, Pack_struc *pack_header, int buffers, int PTSstamp, int DTSstamp ){ int payload = sector_size - (PACKET_HEADER_SIZE + mux_strm.zero_stuffing); if( sys_header != NULL ) payload -= sys_header->length; if( mpeg_version == 2 ) { if( buffers ) payload -= MPEG2_BUFFERINFO_LENGTH; payload -= MPEG2_AFTER_PACKET_LENGTH_MIN; if( pack_header != NULL ) payload -= pack_header->length; if( DTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; if ( PTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; } else { if( buffers ) payload -= MPEG1_BUFFERINFO_LENGTH; payload -= MPEG1_AFTER_PACKET_LENGTH_MIN; if( pack_header != NULL ) payload -= pack_header->length; if( DTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; if (PTSstamp ) payload -= DTS_PTS_TIMESTAMP_LENGTH; if( DTSstamp || PTSstamp ) payload += 1; /* No need for nostamp marker ... */ } return payload;}/************************************************************************* Kopiert einen TimeCode in einen Bytebuffer. Dabei wird er nach MPEG-Verfahren in bits aufgesplittet. Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields for MPEG-1/2 DTS/PTS fields and MPEG-1 pack scr fields*************************************************************************/void PS_Stream::BufferDtsPtsMpeg1ScrTimecode (clockticks timecode, uint8_t marker, uint8_t *&buffer){ clockticks thetime_base; uint8_t temp; unsigned int msb, lsb; /* MPEG-1 uses a 90KHz clock, extended to 300*90KHz = 27Mhz in MPEG-2 */ /* For these fields we only encode to MPEG-1 90Khz resolution... */ thetime_base = timecode /300; msb = (thetime_base >> 32) & 1; lsb = (thetime_base & static_cast<uint64_t>(0xFFFFFFFF)); temp = (marker << 4) | (msb <<3) | ((lsb >> 29) & 0x6) | 1; *(buffer++)=temp; temp = (lsb & 0x3fc00000) >> 22; *(buffer++)=temp; temp = ((lsb & 0x003f8000) >> 14) | 1; *(buffer++)=temp; temp = (lsb & 0x7f80) >> 7; *(buffer++)=temp; temp = ((lsb & 0x007f) << 1) | 1; *(buffer++)=temp;}/************************************************************************* Makes a Copy of a TimeCode in a Buffer, splitting it into bitfields for MPEG-2 pack scr fields which use the full 27Mhz resolution Did they *really* need to put a 27Mhz clock source into the system stream. Does anyone really need it for their decoders? Get real... I guess they thought it might allow someone somewhere to save on a proper clock circuit.*************************************************************************/void PS_Stream::BufferMpeg2ScrTimecode( clockticks timecode, uint8_t *&buffer ){ clockticks thetime_base; unsigned int thetime_ext; uint8_t temp; unsigned int msb, lsb; thetime_base = timecode /300; thetime_ext = timecode % 300; msb = (thetime_base>> 32) & 1; lsb = thetime_base & static_cast<uint64_t>(0xFFFFFFFF); temp = (MARKER_MPEG2_SCR << 6) | (msb << 5) | ((lsb >> 27) & 0x18) | 0x4 | ((lsb >> 28) & 0x3); *(buffer++)=temp; temp = (lsb & 0x0ff00000) >> 20; *(buffer++)=temp; temp = ((lsb & 0x000f8000) >> 12) | 0x4 | ((lsb & 0x00006000) >> 13); *(buffer++)=temp; temp = (lsb & 0x00001fe0) >> 5; *(buffer++)=temp; temp = ((lsb & 0x0000001f) << 3) | 0x4 | ((thetime_ext & 0x00000180) >> 7); *(buffer++)=temp; temp = ((thetime_ext & 0x0000007F) << 1) | 1; *(buffer++)=temp;}/*************************************************************************BufferPaddingPacket - Insert a padding packet of the desired length into the specified Program/System stream buffer**************************************************************************/voidPS_Stream::BufferPaddingPacket( int padding, uint8_t *&buffer ){ uint8_t *index = buffer; int i; assert( (mpeg_version == 2 && padding >= 6) || (mpeg_version == 1 && padding >= 7) ); *(index++) = static_cast<uint8_t>(PACKET_START)>>16; *(index++) = static_cast<uint8_t>(PACKET_START & 0x00ffff)>>8; *(index++) = static_cast<uint8_t>(PACKET_START & 0x0000ff); *(index++) = PADDING_STR; *(index++) = static_cast<uint8_t>((padding - 6) >> 8); *(index++) = static_cast<uint8_t>((padding - 6) & 0xff); if (mpeg_version == 2) { for (i = 0; i < padding - 6; i++) *(index++) = static_cast<uint8_t>(STUFFING_BYTE); } else { *(index++) = 0x0F; for (i = 0; i < padding - 7; i++) *(index++) = static_cast<uint8_t>(STUFFING_BYTE); } buffer = index;}void PS_Stream::BufferSectorHeader( uint8_t *index, Pack_struc *pack, Sys_header_struc *sys_header, uint8_t *&header_end ){ /* Pack header if present */ if (pack != NULL) { memcpy ( index, pack->buf, pack->length); index += pack->length; } /* System header if present */ if (sys_header != NULL) { memcpy (index, sys_header->buf, sys_header->length); index += sys_header->length; } header_end = index;}/****************************************** * * BufferPacketHeader * Construct an MPEG-1/2 header for a packet in the specified * buffer (which *MUST* be long enough) and set points to the start of * the payload and packet length fields. * ******************************************/void PS_Stream::BufferPacketHeader( uint8_t *buf, uint8_t type, unsigned int mpeg_version, bool buffers, unsigned int buffer_size, uint8_t buffer_scale, clockticks PTS, clockticks DTS, uint8_t timestamps, unsigned int min_pes_hdr_len, uint8_t *&size_field, uint8_t *&header_end ){ uint8_t *index = buf; uint8_t *pes_header_len_field = 0; /* konstante Packet Headerwerte eintragen */ /* write constant packet header data */ *(index++) = static_cast<uint8_t>(PACKET_START)>>16; *(index++) = static_cast<uint8_t>(PACKET_START & 0x00ffff)>>8; *(index++) = static_cast<uint8_t>(PACKET_START & 0x0000ff); *(index++) = type; /* we remember this offset so we can fill in the packet size field once we know the actual size... */ size_field = index; index += 2; if( mpeg_version == 1 ) { /* MPEG-1: buffer information */ if (buffers) { *(index++) = static_cast<uint8_t> (0x40 | (buffer_scale << 5) | (buffer_size >> 8)); *(index++) = static_cast<uint8_t> (buffer_size & 0xff); } /* MPEG-1: PTS, PTS & DTS, oder gar nichts? */ /* should we write PTS, PTS & DTS or nothing at all ? */ switch (timestamps) { case TIMESTAMPBITS_NO: *(index++) = MARKER_NO_TIMESTAMPS; break; case TIMESTAMPBITS_PTS: BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_JUST_PTS, index); break; case TIMESTAMPBITS_PTS_DTS: BufferDtsPtsMpeg1ScrTimecode (PTS, MARKER_PTS, index); BufferDtsPtsMpeg1ScrTimecode (DTS, MARKER_DTS, index); break; } } else if( type != PADDING_STR ) { /* MPEG-2 packet syntax header flags. */ /* These *DO NOT* appear in padding packets */ /* TODO: They don't appear in several others either! */ /* First byte: <1,0><PES_scrambling_control:2=0><PES_priority><data_alignment_ind.=0> <copyright=0><original=1> */ *(index++) = 0x81; /* Second byte: PTS PTS_DTS or neither? Buffer info? <PTS_DTS:2><ESCR=0><ES_rate=0> <DSM_trick_mode:2=0><PES_CRC=0><PES_extension=(!!buffers)> */ *(index++) = (timestamps << 6) | (!!buffers); /* Third byte: <PES_header_length:8> */ pes_header_len_field = index; /* To fill in later! */ index++; /* MPEG-2: the timecodes if required */ switch (timestamps) { case TIMESTAMPBITS_PTS: BufferDtsPtsMpeg1ScrTimecode(PTS, MARKER_JUST_PTS, index); break; case TIMESTAMPBITS_PTS_DTS: BufferDtsPtsMpeg1ScrTimecode(PTS, MARKER_PTS, index); BufferDtsPtsMpeg1ScrTimecode(DTS, MARKER_DTS, index); break; } /* MPEG-2 The buffer information in a PES_extension */ if( buffers ) { /* MPEG-2 PES extension header <PES_private_data:1=0><pack_header_field=0> <program_packet_sequence_counter=0> <P-STD_buffer=1><reserved:3=1><{PES_extension_flag_2=0> */ *(index++) = static_cast<uint8_t>(0x1e); *(index++) = static_cast<uint8_t> (0x40 | (buffer_scale << 5) |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -