Example #1
0
MP4EncvAtom::MP4EncvAtom() 
	: MP4Atom("encv")
{
	AddReserved("reserved1", 6); /* 0 */

	AddProperty( /* 1 */
		new MP4Integer16Property("dataReferenceIndex"));

	AddReserved("reserved2", 16); /* 2 */

	AddProperty( /* 3 */
		new MP4Integer16Property("width"));
	AddProperty( /* 4 */
		new MP4Integer16Property("height"));

	AddReserved("reserved3", 14); /* 5 */

	MP4StringProperty* pProp = 
		new MP4StringProperty("compressorName");
	pProp->SetFixedLength(32);
	pProp->SetValue("");
	AddProperty(pProp); /* 6 */
	AddReserved("reserved4", 4); /* 7 */

	ExpectChildAtom("esds", Required, OnlyOne);
	ExpectChildAtom("sinf", Required, OnlyOne);
	ExpectChildAtom("avcC", Optional, OnlyOne);
}	
Example #2
0
MP4Mp4vAtom::MP4Mp4vAtom(MP4File &file)
        : MP4Atom(file, "mp4v")
{
    AddReserved(*this, "reserved1", 6); /* 0 */

    AddProperty( /* 1 */
        new MP4Integer16Property(*this, "dataReferenceIndex"));

    AddReserved(*this, "reserved2", 16); /* 2 */

    AddProperty( /* 3 */
        new MP4Integer16Property(*this, "width"));
    AddProperty( /* 4 */
        new MP4Integer16Property(*this, "height"));

    AddReserved(*this, "reserved3", 14); /* 5 */

    MP4StringProperty* pProp =
        new MP4StringProperty(*this, "compressorName");
    pProp->SetFixedLength(32);
    pProp->SetCountedFormat(true);
    pProp->SetValue("");
    AddProperty(pProp); /* 6 */

    AddReserved(*this, "reserved4", 4); /* 7 */

    ExpectChildAtom("colr", Optional, OnlyOne);
    ExpectChildAtom("esds", Required, OnlyOne);
    ExpectChildAtom("pasp", Optional, OnlyOne);
}
Example #3
0
MP4AvspAtom::MP4AvspAtom() 
	: MP4Atom("avsp")
{
	AddReserved("reserved1", 6); /* 0 */

	AddProperty( /* 1 */
		new MP4Integer16Property("dataReferenceIndex"));

	AddReserved("reserved2", 16); /* 2 */

	AddProperty( /* 3 */
		new MP4Integer16Property("width"));
	AddProperty( /* 4 */
		new MP4Integer16Property("height"));

	AddReserved("reserved3", 14); /* 5 */

	MP4StringProperty* pProp = 
		new MP4StringProperty("compressorName");
	pProp->SetFixedLength(32);
	pProp->SetValue("AVS-M Parameters");
	AddProperty(pProp); /* 6 */

	AddReserved("reserved4", 4); /* 7 */

	ExpectChildAtom("avsc", Required, OnlyOne);
	ExpectChildAtom("btrt", Optional, OnlyOne);
	// for now ExpectChildAtom("m4ds", Optional, OnlyOne);
}
Example #4
0
MP4VideoAtom::MP4VideoAtom (const char *type)
        : MP4Atom(type)
{
    AddReserved("reserved1", 6); /* 0 */

    AddProperty( /* 1 */
        new MP4Integer16Property("dataReferenceIndex"));

    AddReserved("reserved2", 16); /* 2 */

    AddProperty( /* 3 */
        new MP4Integer16Property("width"));
    AddProperty( /* 4 */
        new MP4Integer16Property("height"));

    AddReserved("reserved3", 14); /* 5 */

    MP4StringProperty* pProp =
        new MP4StringProperty("compressorName");
    pProp->SetFixedLength(32);
    pProp->SetCountedFormat(true);
    pProp->SetValue("");
    AddProperty(pProp); /* 6 */

    AddProperty(/* 7 */
        new MP4Integer16Property("depth"));
    AddProperty(/* 8 */
        new MP4Integer16Property("colorTableId"));
    ExpectChildAtom("smi ", Optional, OnlyOne);
}
Example #5
0
void MP4RtpAtom::WriteHntiType()
{
    // since length of string is implicit in size of atom
    // we need to handle this specially, and not write the terminating \0
    MP4StringProperty* pSdp = (MP4StringProperty*)m_pProperties[1];
    pSdp->SetFixedLength(strlen(pSdp->GetValue()));
    MP4Atom::Write();
    pSdp->SetFixedLength(0);
}
Example #6
0
void MP4RtpAtom::AddPropertiesHntiType()
{
    MP4StringProperty* pProp =
        new MP4StringProperty("descriptionFormat");
    pProp->SetFixedLength(4);
    AddProperty(pProp); /* 0 */

    AddProperty( /* 1 */
        new MP4StringProperty("sdpText"));
}
Example #7
0
MP4HdlrAtom::MP4HdlrAtom() 
    : MP4Atom("hdlr")
{
    AddVersionAndFlags(); /* 0, 1 */
    AddReserved("reserved1", 4); /* 2 */
    MP4StringProperty* pProp = new MP4StringProperty("handlerType");
    pProp->SetFixedLength(4);
    AddProperty(pProp); /* 3 */
    AddReserved("reserved2", 12); /* 4 */
    AddProperty( /* 5 */
        new MP4StringProperty("name"));
}
Example #8
0
void MP4SdpAtom::Write()
{
	// since length of string is implicit in size of atom
	// we need to handle this specially, and not write the terminating \0
	MP4StringProperty* pSdp = (MP4StringProperty*)m_pProperties[0];
	const char* sdpText = pSdp->GetValue();
	if (sdpText) {
		pSdp->SetFixedLength(strlen(sdpText));
	}
	MP4Atom::Write();
	pSdp->SetFixedLength(0);
}
Example #9
0
MP4ColrAtom::MP4ColrAtom()
        : MP4Atom("colr")
{
    MP4StringProperty* cpt = new MP4StringProperty("colorParameterType");
    cpt->SetFixedLength(4);
    AddProperty(cpt); /* 0 */

    AddProperty( /* 1 */ new MP4Integer16Property("primariesIndex"));

    AddProperty( /* 2 */ new MP4Integer16Property("transferFunctionIndex"));

    AddProperty( /* 3 */ new MP4Integer16Property("matrixIndex"));
}
Example #10
0
void MP4FtypAtom::Generate() 
{
	MP4Atom::Generate();

	((MP4StringProperty*)m_pProperties[0])->SetValue("mp42");

	MP4StringProperty* pBrandProperty = (MP4StringProperty*)
		((MP4TableProperty*)m_pProperties[3])->GetProperty(0);
	ASSERT(pBrandProperty);
	pBrandProperty->AddValue("mp42");
	pBrandProperty->AddValue("isom");
	((MP4Integer32Property*)m_pProperties[2])->IncrementValue();
	((MP4Integer32Property*)m_pProperties[2])->IncrementValue();
}
Example #11
0
MP4FtypAtom::MP4FtypAtom() 
	: MP4Atom("ftyp")
{
	MP4StringProperty* pProp = new MP4StringProperty("majorBrand");
	pProp->SetFixedLength(4);
	AddProperty(pProp); /* 0 */

	AddProperty( /* 1 */
		new MP4Integer32Property("minorVersion"));

	MP4Integer32Property* pCount = 
		new MP4Integer32Property("compatibleBrandsCount"); 
	pCount->SetImplicit();
	AddProperty(pCount); /* 2 */

	MP4TableProperty* pTable = 
		new MP4TableProperty("compatibleBrands", pCount);
	AddProperty(pTable); /* 3 */

	pProp = new MP4StringProperty("brand");
	pProp->SetFixedLength(4);
	pTable->AddProperty(pProp);
}
Example #12
0
// There is a spec incompatiblity between QT and MP4
// QT says name field is a counted string
// MP4 says name field is a null terminated string
// Here we attempt to make all things work
void MP4HdlrAtom::Read() 
{
    // read all the properties but the "name" field
    ReadProperties(0, 5);

    // take a peek at the next byte
    u_int8_t strLength;
    m_pFile->PeekBytes(&strLength, 1);

    // if the value matches the remaining atom length
    if (m_pFile->GetPosition() + strLength + 1 == GetEnd()) {
        // read a counted string
        MP4StringProperty* pNameProp = 
            (MP4StringProperty*)m_pProperties[5];
        pNameProp->SetCountedFormat(true);
        ReadProperties(5);
        pNameProp->SetCountedFormat(false);
    } else {
        // read a null terminated string
        ReadProperties(5);
    }

    Skip();    // to end of atom
}
Example #13
0
void MP4File::MakeFtypAtom(char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount)
{
    bool rewriteNeeded = false;
    u_int32_t currentSupportedBrandsCount;
    u_int32_t i;


    MP4Atom* ftypAtom = m_pRootAtom->FindAtom("ftyp");
    if (ftypAtom == NULL) {
        ftypAtom = InsertChildAtom(m_pRootAtom, "ftyp", 0);
    }
    if (majorBrand == NULL)
        return;
    MP4StringProperty* pMajorBrandProperty;
    if (!ftypAtom->FindProperty(
                "ftyp.majorBrand",
                (MP4Property**)&pMajorBrandProperty))
        return;

    pMajorBrandProperty->SetValue(majorBrand);


    MP4Integer32Property* pMinorVersionProperty;
    if (!ftypAtom->FindProperty(
                "ftype.minorVersion",
                (MP4Property**)&pMinorVersionProperty))
        return;

    pMinorVersionProperty->SetValue(minorVersion);

    MP4Integer32Property* pCompatibleBrandsCountProperty;
    if (!ftypAtom->FindProperty(
                "ftyp.compatibleBrandsCount",
                (MP4Property**)&pCompatibleBrandsCountProperty)) return;

    currentSupportedBrandsCount = pCompatibleBrandsCountProperty->GetValue();

    MP4TableProperty* pCompatibleBrandsProperty;
    if (!ftypAtom->FindProperty(
                "ftyp.compatibleBrands",
                (MP4Property**)&pCompatibleBrandsProperty)) return;

    MP4StringProperty* pBrandProperty = (MP4StringProperty*)
                                        pCompatibleBrandsProperty->GetProperty(0);
    ASSERT(pBrandProperty);

    for (i = 0 ; i < ((currentSupportedBrandsCount > supportedBrandsCount) ? supportedBrandsCount : currentSupportedBrandsCount) ; i++) {
        pBrandProperty->SetValue(supportedBrands[i], i);

    }

    if (i < supportedBrandsCount) {
        for ( ; i < supportedBrandsCount ; i++) {
            pBrandProperty->AddValue(supportedBrands[i]);
        }
    }

    if (currentSupportedBrandsCount != supportedBrandsCount) {
        rewriteNeeded = true;
        pBrandProperty->SetCount(supportedBrandsCount);
        pCompatibleBrandsCountProperty->SetReadOnly(false);
        pCompatibleBrandsCountProperty->SetValue(supportedBrandsCount);
        pCompatibleBrandsCountProperty->SetReadOnly(true);
    }

}
Example #14
0
FILE* MP4Track::GetSampleFile(MP4SampleId sampleId)
{
	u_int32_t stscIndex =
		GetSampleStscIndex(sampleId);

	u_int32_t stsdIndex = 
		m_pStscSampleDescrIndexProperty->GetValue(stscIndex);

	// check if the answer will be the same as last time
	if (m_lastStsdIndex && stsdIndex == m_lastStsdIndex) {
		return m_lastSampleFile;
	}

	MP4Atom* pStsdAtom = 
		m_pTrakAtom->FindAtom("trak.mdia.minf.stbl.stsd");
	ASSERT(pStsdAtom);

	MP4Atom* pStsdEntryAtom = 
		pStsdAtom->GetChildAtom(stsdIndex - 1);
	ASSERT(pStsdEntryAtom);

	MP4Integer16Property* pDrefIndexProperty = NULL;
	pStsdEntryAtom->FindProperty(
		"*.dataReferenceIndex",
		(MP4Property**)&pDrefIndexProperty);
	
	if (pDrefIndexProperty == NULL) {
		throw new MP4Error("invalid stsd entry", "GetSampleFile");
	}

	u_int32_t drefIndex =
		pDrefIndexProperty->GetValue();

	MP4Atom* pDrefAtom =
		m_pTrakAtom->FindAtom("trak.mdia.minf.dinf.dref");
	ASSERT(pDrefAtom);

	MP4Atom* pUrlAtom =
		pDrefAtom->GetChildAtom(drefIndex - 1);
	ASSERT(pUrlAtom);

	FILE* pFile;

	if (pUrlAtom->GetFlags() & 1) {
		pFile = NULL;	// self-contained
	} else {
#ifndef USE_FILE_CALLBACKS
		MP4StringProperty* pLocationProperty = NULL;
		pUrlAtom->FindProperty(
			"*.location", 
			(MP4Property**)&pLocationProperty);
		ASSERT(pLocationProperty);

		const char* url = pLocationProperty->GetValue();

		VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
			printf("dref url = %s\n", url));

		pFile = (FILE*)-1;

		// attempt to open url if it's a file url 
		// currently this is the only thing we understand
		if (!strncmp(url, "file:", 5)) {
			const char* fileName = url + 5;
			if (!strncmp(fileName, "//", 2)) {
				fileName = strchr(fileName + 2, '/');
			}
			if (fileName) {
				pFile = fopen(fileName, "rb");
				if (!pFile) {
					pFile = (FILE*)-1;
				}
			}
		} 
#else
        throw new MP4Error(errno, "Function not supported when using callbacks", "GetSampleFile");
#endif
	}

	if (m_lastSampleFile) {
#ifndef USE_FILE_CALLBACKS
		fclose(m_lastSampleFile);
#else
        throw new MP4Error(errno, "Function not supported when using callbacks", "GetSampleFile");
#endif
	}

	// cache the answer
	m_lastStsdIndex = stsdIndex;
	m_lastSampleFile = pFile;

	return pFile;
}
Example #15
0
MP4Descriptor* MP4File::CreateESD(
    MP4DescriptorProperty* pEsProperty,
    u_int32_t esid,
    u_int8_t objectType,
    u_int8_t streamType,
    u_int32_t bufferSize,
    u_int32_t bitrate,
    u_int8_t* pConfig,
    u_int32_t configLength,
    char* url)
{
    MP4IntegerProperty* pInt;
    MP4StringProperty* pString;
    MP4BytesProperty* pBytes;
    MP4BitfieldProperty* pBits;

    MP4Descriptor* pEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pEsd->Generate();

    pEsd->FindProperty("ESID",
                       (MP4Property**)&pInt);
    pInt->SetValue(esid);

    pEsd->FindProperty("decConfigDescr.objectTypeId",
                       (MP4Property**)&pInt);
    pInt->SetValue(objectType);

    pEsd->FindProperty("decConfigDescr.streamType",
                       (MP4Property**)&pInt);
    pInt->SetValue(streamType);

    pEsd->FindProperty("decConfigDescr.bufferSizeDB",
                       (MP4Property**)&pInt);
    pInt->SetValue(bufferSize);

    pEsd->FindProperty("decConfigDescr.maxBitrate",
                       (MP4Property**)&pInt);
    pInt->SetValue(bitrate);

    pEsd->FindProperty("decConfigDescr.avgBitrate",
                       (MP4Property**)&pInt);
    pInt->SetValue(bitrate);

    MP4DescriptorProperty* pConfigDescrProperty;
    pEsd->FindProperty("decConfigDescr.decSpecificInfo",
                       (MP4Property**)&pConfigDescrProperty);

    MP4Descriptor* pConfigDescr =
        pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag);
    pConfigDescr->Generate();

    pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
                                       (MP4Property**)&pBytes);
    pBytes->SetValue(pConfig, configLength);

    pEsd->FindProperty("slConfigDescr.predefined",
                       (MP4Property**)&pInt);
    // changed 12/5/02 from plugfest to value 0
    pInt->SetValue(0);

    pEsd->FindProperty("slConfig.useAccessUnitEndFlag",
                       (MP4Property **)&pBits);
    pBits->SetValue(1);

    if (url) {
        pEsd->FindProperty("URLFlag",
                           (MP4Property**)&pInt);
        pInt->SetValue(1);

        pEsd->FindProperty("URL",
                           (MP4Property**)&pString);
        pString->SetValue(url);
    }

    return pEsd;
}
Example #16
0
void MP4File::CreateIsmaIodFromFile(
    MP4TrackId odTrackId,
    MP4TrackId sceneTrackId,
    MP4TrackId audioTrackId,
    MP4TrackId videoTrackId,
    u_int8_t** ppBytes,
    u_int64_t* pNumBytes)
{
    MP4Descriptor* pIod = new MP4IODescriptor();
    pIod->SetTag(MP4IODescrTag);
    pIod->Generate();

    MP4Atom* pIodsAtom = FindAtom("moov.iods");
    ASSERT(pIodsAtom);
    MP4DescriptorProperty* pSrcIod =
        (MP4DescriptorProperty*)pIodsAtom->GetProperty(2);

    CloneIntegerProperty(pIod, pSrcIod, "objectDescriptorId");
    CloneIntegerProperty(pIod, pSrcIod, "ODProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "sceneProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "audioProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "visualProfileLevelId");
    CloneIntegerProperty(pIod, pSrcIod, "graphicsProfileLevelId");

    // mutate esIds from MP4ESIDIncDescrTag to MP4ESDescrTag
    MP4DescriptorProperty* pEsProperty;
    pIod->FindProperty("esIds", (MP4Property**)&pEsProperty);
    pEsProperty->SetTags(MP4ESDescrTag);

    MP4IntegerProperty* pSetProperty;
    MP4IntegerProperty* pSceneESID;
    MP4IntegerProperty* pOdESID;

    // OD
    MP4Descriptor* pOdEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pOdEsd->Generate();

    pOdEsd->FindProperty("ESID",
                         (MP4Property**)&pOdESID);

    // we set the OD ESID to a non-zero unique value
    pOdESID->SetValue(m_odTrackId);

    pOdEsd->FindProperty("URLFlag",
                         (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);

    u_int8_t* pBytes;
    u_int64_t numBytes;

    CreateIsmaODUpdateCommandFromFileForStream(
        audioTrackId,
        videoTrackId,
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data =\n"); MP4HexDump(pBytes, numBytes));

    char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);

    char* urlBuf = (char*)MP4Malloc(strlen(odCmdBase64) + 64);

    sprintf(urlBuf,
            "data:application/mpeg4-od-au;base64,%s",
            odCmdBase64);

    MP4StringProperty* pUrlProperty;
    pOdEsd->FindProperty("URL",
                         (MP4Property**)&pUrlProperty);
    pUrlProperty->SetValue(urlBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("OD data URL = \042%s\042\n", urlBuf));

    MP4Free(odCmdBase64);
    odCmdBase64 = NULL;
    MP4Free(pBytes);
    pBytes = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;

    MP4DescriptorProperty* pSrcDcd = NULL;

    // HACK temporarily point to scene decoder config
    FindProperty(MakeTrackName(odTrackId,
                               "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
                 (MP4Property**)&pSrcDcd);
    ASSERT(pSrcDcd);
    MP4Property* pOrgOdEsdProperty =
        pOdEsd->GetProperty(8);
    pOdEsd->SetProperty(8, pSrcDcd);

    // bufferSizeDB needs to be set appropriately
    MP4BitfieldProperty* pBufferSizeProperty = NULL;
    pOdEsd->FindProperty("decConfigDescr.bufferSizeDB",
                         (MP4Property**)&pBufferSizeProperty);
    ASSERT(pBufferSizeProperty);
    pBufferSizeProperty->SetValue(numBytes);

    // SL config needs to change from 2 (file) to 1 (null)
    pOdEsd->FindProperty("slConfigDescr.predefined",
                         (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);


    // Scene
    MP4Descriptor* pSceneEsd =
        pEsProperty->AddDescriptor(MP4ESDescrTag);
    pSceneEsd->Generate();

    pSceneEsd->FindProperty("ESID",
                            (MP4Property**)&pSceneESID);
    // we set the Scene ESID to a non-zero unique value
    pSceneESID->SetValue(sceneTrackId);

    pSceneEsd->FindProperty("URLFlag",
                            (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);

    CreateIsmaSceneCommand(
        MP4_IS_VALID_TRACK_ID(audioTrackId),
        MP4_IS_VALID_TRACK_ID(videoTrackId),
        &pBytes,
        &numBytes);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data =\n"); MP4HexDump(pBytes, numBytes));

    char *sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);

    urlBuf = (char*)MP4Malloc(strlen(sceneCmdBase64) + 64);
    sprintf(urlBuf,
            "data:application/mpeg4-bifs-au;base64,%s",
            sceneCmdBase64);

    pSceneEsd->FindProperty("URL",
                            (MP4Property**)&pUrlProperty);
    pUrlProperty->SetValue(urlBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("Scene data URL = \042%s\042\n", urlBuf));

    MP4Free(sceneCmdBase64);
    sceneCmdBase64 = NULL;
    MP4Free(urlBuf);
    urlBuf = NULL;
    MP4Free(pBytes);
    pBytes = NULL;

    // HACK temporarily point to scene decoder config
    FindProperty(MakeTrackName(sceneTrackId,
                               "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr"),
                 (MP4Property**)&pSrcDcd);
    ASSERT(pSrcDcd);
    MP4Property* pOrgSceneEsdProperty =
        pSceneEsd->GetProperty(8);
    pSceneEsd->SetProperty(8, pSrcDcd);

    // bufferSizeDB needs to be set
    pBufferSizeProperty = NULL;
    pSceneEsd->FindProperty("decConfigDescr.bufferSizeDB",
                            (MP4Property**)&pBufferSizeProperty);
    ASSERT(pBufferSizeProperty);
    pBufferSizeProperty->SetValue(numBytes);

    // SL config needs to change from 2 (file) to 1 (null)
    pSceneEsd->FindProperty("slConfigDescr.predefined",
                            (MP4Property**)&pSetProperty);
    pSetProperty->SetValue(1);


    // finally get the whole thing written to a memory
    pIod->WriteToMemory(this, ppBytes, pNumBytes);


    // now carefully replace esd properties before destroying
    pOdEsd->SetProperty(8, pOrgOdEsdProperty);
    pSceneEsd->SetProperty(8, pOrgSceneEsdProperty);
    pSceneESID->SetValue(0); // restore 0 value
    pOdESID->SetValue(0);

    delete pIod;

    VERBOSE_ISMA(GetVerbosity(),
                 printf("IOD data =\n"); MP4HexDump(*ppBytes, *pNumBytes));
}