📄 slc.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project * * GPAC 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, or (at your option) * any later version. * * GPAC 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; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/odf_dev.h>//// Constructor//GF_Descriptor *gf_odf_new_slc(u8 predef){ GF_SLConfig *newDesc = (GF_SLConfig *) malloc(sizeof(GF_SLConfig)); if (!newDesc) return NULL; memset(newDesc, 0, sizeof(GF_SLConfig)); newDesc->tag = GF_ODF_SLC_TAG; newDesc->predefined = predef; if (predef) gf_odf_slc_set_pref(newDesc); newDesc->useTimestampsFlag = 1; return (GF_Descriptor *)newDesc;}//// Destructor//GF_Err gf_odf_del_slc(GF_SLConfig *sl){ if (!sl) return GF_BAD_PARAM; free(sl); return GF_OK;}//// Set the SL to the ISO predefined value//GF_EXPORTGF_Err gf_odf_slc_set_pref(GF_SLConfig *sl){ if (! sl) return GF_BAD_PARAM; switch (sl->predefined) { case SLPredef_MP4: sl->useAccessUnitStartFlag = 0; sl->useAccessUnitEndFlag = 0; //each packet is an AU, and we need RAP signaling sl->useRandomAccessPointFlag = 1; sl->hasRandomAccessUnitsOnlyFlag = 0; sl->usePaddingFlag = 0; //in MP4 file, we use TimeStamps sl->useTimestampsFlag = 1; sl->useIdleFlag = 0; sl->durationFlag = 0; sl->timestampLength = 0; sl->OCRLength = 0; sl->AULength = 0; sl->instantBitrateLength = 0; sl->degradationPriorityLength = 0; sl->AUSeqNumLength = 0; sl->packetSeqNumLength = 0; break; case SLPredef_Null: sl->useAccessUnitStartFlag = 0; sl->useAccessUnitEndFlag = 0; sl->useRandomAccessPointFlag = 0; sl->hasRandomAccessUnitsOnlyFlag = 0; sl->usePaddingFlag = 0; sl->useTimestampsFlag = 0; sl->useIdleFlag = 0; sl->AULength = 0; sl->degradationPriorityLength = 0; sl->AUSeqNumLength = 0; sl->packetSeqNumLength = 0; //for MPEG4 IP sl->timestampResolution = 1000; sl->timestampLength = 32; break; case SLPredef_SkipSL: sl->predefined = SLPredef_SkipSL; break; /*handle all unknown predefined as predef-null*/ default: sl->useAccessUnitStartFlag = 0; sl->useAccessUnitEndFlag = 0; sl->useRandomAccessPointFlag = 0; sl->hasRandomAccessUnitsOnlyFlag = 0; sl->usePaddingFlag = 0; sl->useTimestampsFlag = 1; sl->useIdleFlag = 0; sl->AULength = 0; sl->degradationPriorityLength = 0; sl->AUSeqNumLength = 0; sl->packetSeqNumLength = 0; sl->timestampResolution = 1000; sl->timestampLength = 32; break; } return GF_OK;}u32 SLIsPredefined(GF_SLConfig *sl){ if (!sl) return 0; if (sl->predefined) return sl->predefined; if (!sl->useAccessUnitStartFlag && !sl->useAccessUnitEndFlag && !sl->usePaddingFlag && sl->useTimestampsFlag && !sl->useIdleFlag && !sl->durationFlag && !sl->timestampLength && !sl->OCRLength && !sl->AULength && !sl->instantBitrateLength && !sl->degradationPriorityLength && !sl->AUSeqNumLength && !sl->packetSeqNumLength) return SLPredef_MP4; return 0;}//this function gets the real amount of bytes needed to store the timeStampstatic u32 GetTSbytesLen(GF_SLConfig *sl){ u32 TSlen, TSbytes; if (! sl) return 0; TSlen = sl->timestampLength * 2; TSbytes = TSlen / 8; TSlen = TSlen % 8; if (TSlen) TSbytes += 1; return TSbytes;}//// Reader//GF_Err gf_odf_read_slc(GF_BitStream *bs, GF_SLConfig *sl, u32 DescSize){ GF_Err e; u32 reserved, nbBytes = 0; if (!sl) return GF_BAD_PARAM; //APPLE fix if (!DescSize) { sl->predefined = SLPredef_MP4; return gf_odf_slc_set_pref(sl); } sl->predefined = gf_bs_read_int(bs, 8); nbBytes += 1; /*MPEG4 IP fix*/ if (!sl->predefined && nbBytes==DescSize) { sl->predefined = SLPredef_Null; gf_odf_slc_set_pref(sl); return GF_OK; } if (sl->predefined) { //predefined configuration e = gf_odf_slc_set_pref(sl); if (e) return e; } else { sl->useAccessUnitStartFlag = gf_bs_read_int(bs, 1); sl->useAccessUnitEndFlag = gf_bs_read_int(bs, 1); sl->useRandomAccessPointFlag = gf_bs_read_int(bs, 1); sl->hasRandomAccessUnitsOnlyFlag = gf_bs_read_int(bs, 1); sl->usePaddingFlag = gf_bs_read_int(bs, 1); sl->useTimestampsFlag = gf_bs_read_int(bs, 1); sl->useIdleFlag = gf_bs_read_int(bs, 1); sl->durationFlag = gf_bs_read_int(bs, 1); sl->timestampResolution = gf_bs_read_int(bs, 32); sl->OCRResolution = gf_bs_read_int(bs, 32); sl->timestampLength = gf_bs_read_int(bs, 8); if (sl->timestampLength > 64) return GF_ODF_INVALID_DESCRIPTOR; sl->OCRLength = gf_bs_read_int(bs, 8); if (sl->OCRLength > 64) return GF_ODF_INVALID_DESCRIPTOR; sl->AULength = gf_bs_read_int(bs, 8); if (sl->AULength > 32) return GF_ODF_INVALID_DESCRIPTOR; sl->instantBitrateLength = gf_bs_read_int(bs, 8); sl->degradationPriorityLength = gf_bs_read_int(bs, 4); sl->AUSeqNumLength = gf_bs_read_int(bs, 5); if (sl->AUSeqNumLength > 16) return GF_ODF_INVALID_DESCRIPTOR; sl->packetSeqNumLength = gf_bs_read_int(bs, 5); if (sl->packetSeqNumLength > 16) return GF_ODF_INVALID_DESCRIPTOR; reserved = gf_bs_read_int(bs, 2); nbBytes += 15; } if (sl->durationFlag) { sl->timeScale = gf_bs_read_int(bs, 32); sl->AUDuration = gf_bs_read_int(bs, 16); sl->CUDuration = gf_bs_read_int(bs, 16); nbBytes += 8; } if (! sl->useTimestampsFlag) { sl->startDTS = gf_bs_read_long_int(bs, sl->timestampLength); sl->startCTS = gf_bs_read_long_int(bs, sl->timestampLength); nbBytes += GetTSbytesLen(sl); } if (DescSize != nbBytes) return GF_ODF_INVALID_DESCRIPTOR; return GF_OK;}//// Size//GF_Err gf_odf_size_slc(GF_SLConfig *sl, u32 *outSize){ if (! sl) return GF_BAD_PARAM; *outSize = 1; if (! sl->predefined) *outSize += 15; if (sl->durationFlag) *outSize += 8; if (! sl->useTimestampsFlag) *outSize += GetTSbytesLen(sl); return GF_OK;}//// Writer//GF_Err gf_odf_write_slc(GF_BitStream *bs, GF_SLConfig *sl){ GF_Err e; u32 size; if (! sl) return GF_BAD_PARAM; e = gf_odf_size_descriptor((GF_Descriptor *)sl, &size); e = gf_odf_write_base_descriptor(bs, sl->tag, size); gf_bs_write_int(bs, sl->predefined, 8); if (! sl->predefined) { gf_bs_write_int(bs, sl->useAccessUnitStartFlag, 1); gf_bs_write_int(bs, sl->useAccessUnitEndFlag, 1); gf_bs_write_int(bs, sl->useRandomAccessPointFlag, 1); gf_bs_write_int(bs, sl->hasRandomAccessUnitsOnlyFlag, 1); gf_bs_write_int(bs, sl->usePaddingFlag, 1); gf_bs_write_int(bs, sl->useTimestampsFlag, 1); gf_bs_write_int(bs, sl->useIdleFlag, 1); gf_bs_write_int(bs, sl->durationFlag, 1); gf_bs_write_int(bs, sl->timestampResolution, 32); gf_bs_write_int(bs, sl->OCRResolution, 32); gf_bs_write_int(bs, sl->timestampLength, 8); gf_bs_write_int(bs, sl->OCRLength, 8); gf_bs_write_int(bs, sl->AULength, 8); gf_bs_write_int(bs, sl->instantBitrateLength, 8); gf_bs_write_int(bs, sl->degradationPriorityLength, 4); gf_bs_write_int(bs, sl->AUSeqNumLength, 5); gf_bs_write_int(bs, sl->packetSeqNumLength, 5); gf_bs_write_int(bs, 3, 2); //reserved: 0b11 == 3 } if (sl->durationFlag) { gf_bs_write_int(bs, sl->timeScale, 32); gf_bs_write_int(bs, sl->AUDuration, 16); gf_bs_write_int(bs, sl->CUDuration, 16); } if (! sl->useTimestampsFlag) { gf_bs_write_long_int(bs, sl->startDTS, sl->timestampLength); gf_bs_write_long_int(bs, sl->startCTS, sl->timestampLength); } return GF_OK;}/*allocates and writes the SL-PDU (Header + PDU) given the SLConfig and the GF_SLHeaderfor this PDU. AUs must be split in PDUs by another process if needed (packetizer).*/GF_EXPORTvoid gf_sl_packetize(GF_SLConfig* slConfig, GF_SLHeader *Header, char *PDU, u32 size, char **outPacket, u32 *OutSize){ GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); *OutSize = 0; if (!bs) return; if (slConfig->useAccessUnitStartFlag) gf_bs_write_int(bs, Header->accessUnitStartFlag, 1); if (slConfig->useAccessUnitEndFlag) gf_bs_write_int(bs, Header->accessUnitEndFlag, 1); if (slConfig->OCRLength > 0) gf_bs_write_int(bs, Header->OCRflag, 1); if (slConfig->useIdleFlag) gf_bs_write_int(bs, Header->idleFlag, 1); if (slConfig->usePaddingFlag) { gf_bs_write_int(bs, Header->paddingFlag, 1); if (Header->paddingFlag) gf_bs_write_int(bs, Header->paddingBits, 3); } if (! Header->idleFlag && (! Header->paddingFlag || Header->paddingBits != 0)) { if (slConfig->packetSeqNumLength > 0) gf_bs_write_int(bs, Header->packetSequenceNumber, slConfig->packetSeqNumLength); if (slConfig->degradationPriorityLength > 0) { gf_bs_write_int(bs, Header->degradationPriorityFlag, 1); if (Header->degradationPriorityFlag) gf_bs_write_int(bs, Header->degradationPriority, slConfig->degradationPriorityLength); } if (Header->OCRflag) gf_bs_write_long_int(bs, Header->objectClockReference, slConfig->OCRLength); if (Header->accessUnitStartFlag) { if (slConfig->useRandomAccessPointFlag) gf_bs_write_int(bs, Header->randomAccessPointFlag, 1); if (slConfig->AUSeqNumLength > 0) gf_bs_write_int(bs, Header->AU_sequenceNumber, slConfig->AUSeqNumLength); if (slConfig->useTimestampsFlag) { gf_bs_write_int(bs, Header->decodingTimeStampFlag, 1); gf_bs_write_int(bs, Header->compositionTimeStampFlag, 1); } if (slConfig->instantBitrateLength > 0) gf_bs_write_int(bs, Header->instantBitrateFlag, 1); if (Header->decodingTimeStampFlag) gf_bs_write_long_int(bs, Header->decodingTimeStamp, slConfig->timestampLength); if (Header->compositionTimeStampFlag) gf_bs_write_long_int(bs, Header->compositionTimeStamp, slConfig->timestampLength); if (slConfig->AULength > 0) gf_bs_write_int(bs, Header->accessUnitLength, slConfig->AULength); if (Header->instantBitrateFlag) gf_bs_write_int(bs, Header->instantBitrate, slConfig->instantBitrateLength); } } //done with the Header, Alin gf_bs_align(bs); //write the PDU - already byte aligned with stuffing (paddingBits in SL Header) gf_bs_write_data(bs, PDU, size); gf_bs_align(bs); gf_bs_get_content(bs, outPacket, OutSize); gf_bs_del(bs);}GF_EXPORTvoid gf_sl_depacketize (GF_SLConfig *slConfig, GF_SLHeader *Header, char *PDU, u32 PDULength, u32 *HeaderLen){ GF_BitStream *bs; *HeaderLen = 0; if (!Header) return; //reset the input header memset(Header, 0, sizeof(GF_SLHeader)); bs = gf_bs_new(PDU, PDULength, GF_BITSTREAM_READ); if (!bs) return; if (slConfig->useAccessUnitStartFlag) Header->accessUnitStartFlag = gf_bs_read_int(bs, 1); if (slConfig->useAccessUnitEndFlag) Header->accessUnitEndFlag = gf_bs_read_int(bs, 1); if ( !slConfig->useAccessUnitStartFlag && !slConfig->useAccessUnitEndFlag) { Header->accessUnitStartFlag = 1; Header->accessUnitEndFlag = 1; } if (slConfig->OCRLength > 0) Header->OCRflag = gf_bs_read_int(bs, 1); if (slConfig->useIdleFlag) Header->idleFlag = gf_bs_read_int(bs, 1); if (slConfig->usePaddingFlag) { Header->paddingFlag = gf_bs_read_int(bs, 1); if (Header->paddingFlag) Header->paddingBits = gf_bs_read_int(bs, 3); } if (!Header->idleFlag && (!Header->paddingFlag || Header->paddingBits != 0)) { if (slConfig->packetSeqNumLength > 0) Header->packetSequenceNumber = gf_bs_read_int(bs, slConfig->packetSeqNumLength); if (slConfig->degradationPriorityLength > 0) { Header->degradationPriorityFlag = gf_bs_read_int(bs, 1); if (Header->degradationPriorityFlag) Header->degradationPriority = gf_bs_read_int(bs, slConfig->degradationPriorityLength); } if (Header->OCRflag) Header->objectClockReference = gf_bs_read_int(bs, slConfig->OCRLength); if (Header->accessUnitStartFlag) { if (slConfig->useRandomAccessPointFlag) Header->randomAccessPointFlag = gf_bs_read_int(bs, 1); if (slConfig->AUSeqNumLength > 0) Header->AU_sequenceNumber = gf_bs_read_int(bs, slConfig->AUSeqNumLength); if (slConfig->useTimestampsFlag) { Header->decodingTimeStampFlag = gf_bs_read_int(bs, 1); Header->compositionTimeStampFlag = gf_bs_read_int(bs, 1); } if (slConfig->instantBitrateLength > 0) Header->instantBitrateFlag = gf_bs_read_int(bs, 1); if (Header->decodingTimeStampFlag) Header->decodingTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength); if (Header->compositionTimeStampFlag) Header->compositionTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength); if (slConfig->AULength > 0) Header->accessUnitLength = gf_bs_read_int(bs, slConfig->AULength); if (Header->instantBitrateFlag) Header->instantBitrate = gf_bs_read_int(bs, slConfig->instantBitrateLength); } } gf_bs_align(bs); *HeaderLen = (u32) gf_bs_get_position(bs); gf_bs_del(bs);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -