Live555对于将ES流封装成TS文件的部分代码

本文档详细介绍了Live555库中MPEG2TransportStreamMultiplexor类的实现,该类用于将 Elementary Stream (ES) 流封装成 MPEG-2 Transport Stream (TS) 包。代码涵盖了PAT和PMT表的生成,以及如何处理不同类型的PID流。通过对同步字节、包头、PCR和适应字段的处理,展示了TS包的构造过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

若要将编码器产生的音频视频流在苹果公司的产品上播放,需要使用苹果公司所支持的HLS协议,而开源的live555库中有对于将ES流封装成TS流的代码实现,曾花了一段时间研究MPEG2-TS的格式,并且也阅读和调试了这部分代码,确实结构非常巧妙,系统资源也占用得非常少。
/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)

This library 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 Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
**********/
// "liveMedia"
// Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
// A class for generating MPEG-2 Transport Stream from one or more input
// Elementary Stream data sources
// Implementation

#include "MPEG2TransportStreamMultiplexor.hh"

#define TRANSPORT_PACKET_SIZE 188 //TS包长为188个字节

#define PAT_FREQUENCY 100 // # of packets between Program Association Tables //PAT表出现的频率
#define PMT_FREQUENCY 500 // # of packets between Program Map Tables //PMT表出现的频率

#define PID_TABLE_SIZE 256 //PID 用来标识流

MPEG2TransportStreamMultiplexor
::MPEG2TransportStreamMultiplexor(UsageEnvironment& env)
  : FramedSource(env),
    fHaveVideoStreams(True/*by default*/),
    fOutgoingPacketCounter(0), fProgramMapVersion(0),
    fPreviousInputProgramMapVersion(0xFF), fCurrentInputProgramMapVersion(0xFF),
    fPCR_PID(0), fCurrentPID(0),
    fInputBuffer(NULL), fInputBufferSize(0), fInputBufferBytesUsed(0),
    fIsFirstAdaptationField(True) {
  for (unsigned i = 0; i < PID_TABLE_SIZE; ++i) {
    fPIDState[i].counter = 0;
    fPIDState[i].streamType = 0;
  }
}

MPEG2TransportStreamMultiplexor::~MPEG2TransportStreamMultiplexor() {
}

void MPEG2TransportStreamMultiplexor::doGetNextFrame() {
  if (fInputBufferBytesUsed >= fInputBufferSize) {
    // No more bytes are available from the current buffer.
    // Arrange to read a new one.
    awaitNewBuffer(fInputBuffer);
    return;
  }

  do {
    // Periodically return a Program Association Table packet instead:
    if (fOutgoingPacketCounter++ % PAT_FREQUENCY == 0) {//注意这里的书写逻辑
      deliverPATPacket();//发送PAT表
      break;
    }

    // Periodically (or when we see a new PID) return a Program Map Table instead:
    Boolean programMapHasChanged = fPIDState[fCurrentPID].counter == 0
      || fCurrentInputProgramMapVersion != fPreviousInputProgramMapVersion;
    if (fOutgoingPacketCounter % PMT_FREQUENCY == 0 || programMapHasChanged) {//需发送PMT表时以及节目变化时
      if (programMapHasChanged) { // reset values for next time:
	fPIDState[fCurrentPID].counter = 1;
	fPreviousInputProgramMapVersion = fCurrentInputProgramMapVersion;
      }
      deliverPMTPacket(programMapHasChanged);
      break;
    }

    // Normal case: Deliver (or continue delivering) the recently-read data:
    deliverDataToClient(fCurrentPID, fInputBuffer, fInputBufferSize,
			fInputBufferBytesUsed);
  } while (0);

  // NEED TO SET fPresentationTime, durationInMicroseconds #####
  // Complete the delivery to the client:
  afterGetting(this);
}

void MPEG2TransportStreamMultiplexor
::handleNewBuffer(unsigned char* buffer, unsigned bufferSize,
		  int mpegVersion, MPEG1or2Demux::SCR scr) {
  if (bufferSize < 4) 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值