示例#1
0
void MP4BytesProperty::SetValue(const u_int8_t* pValue, u_int32_t valueSize, 
	u_int32_t index) 
{
	if (m_readOnly) {
		throw new MP4Error(EACCES, "property is read-only", m_name);
	}
	if (m_fixedValueSize) {
		if (valueSize > m_fixedValueSize) {
			throw new MP4Error("value size exceeds fixed value size",
				"MP4BytesProperty::SetValue");
		}
		if (m_values[index] == NULL) {
			m_values[index] = (u_int8_t*)MP4Calloc(m_fixedValueSize);
			m_valueSizes[index] = m_fixedValueSize;
		}
		if (pValue) {
			memcpy(m_values[index], pValue, valueSize);
		}
	} else {
		MP4Free(m_values[index]);
		if (pValue) {
			m_values[index] = (u_int8_t*)MP4Malloc(valueSize);
			memcpy(m_values[index], pValue, valueSize);
			m_valueSizes[index] = valueSize;
		} else {
			m_values[index] = NULL;
			m_valueSizes[index] = 0;
		}
	}
}
示例#2
0
void MP4Track::ReadSampleFragment(
	MP4SampleId sampleId,
	u_int32_t sampleOffset,
	u_int16_t sampleLength,
	u_int8_t* pDest)
{
	if (sampleId == MP4_INVALID_SAMPLE_ID) {
		throw new MP4Error("invalid sample id", 
			"MP4Track::ReadSampleFragment");
	}

	if (sampleId != m_cachedReadSampleId) {
		MP4Free(m_pCachedReadSample);
		m_pCachedReadSample = NULL;
		m_cachedReadSampleSize = 0;
		m_cachedReadSampleId = MP4_INVALID_SAMPLE_ID;

		ReadSample(
			sampleId,
			&m_pCachedReadSample,
			&m_cachedReadSampleSize);

		m_cachedReadSampleId = sampleId;
	}

	if (sampleOffset + sampleLength > m_cachedReadSampleSize) {
		throw new MP4Error("offset and/or length are too large", 
			"MP4Track::ReadSampleFragment");
	}

	memcpy(pDest, &m_pCachedReadSample[sampleOffset], sampleLength);
}
示例#3
0
MP4BytesProperty::~MP4BytesProperty() 
{
	u_int32_t count = GetCount();
	for (u_int32_t i = 0; i < count; i++) {
		MP4Free(m_values[i]);
	}
}
示例#4
0
void MP4Track::WriteChunkBuffer()
{
	if (m_chunkBufferSize == 0) {
		return;
	}

	u_int64_t chunkOffset = m_pFile->GetPosition();

	// write chunk buffer
	m_pFile->WriteBytes(m_pChunkBuffer, m_chunkBufferSize);

	VERBOSE_WRITE_SAMPLE(m_pFile->GetVerbosity(),
		printf("WriteChunk: track %u offset 0x"LLX" size %u (0x%x) numSamples %u\n",
			m_trackId, chunkOffset, m_chunkBufferSize, 
			m_chunkBufferSize, m_chunkSamples));

	UpdateSampleToChunk(m_writeSampleId, 
		m_pChunkCountProperty->GetValue() + 1, 
		m_chunkSamples);

	UpdateChunkOffsets(chunkOffset);

	// clean up chunk buffer
	MP4Free(m_pChunkBuffer);
	m_pChunkBuffer = NULL;
	m_chunkBufferSize = 0;
	m_chunkSamples = 0;
	m_chunkDuration = 0;
}
示例#5
0
void MP4BytesProperty::Read(MP4File* pFile, u_int32_t index)
{
	if (m_implicit) {
		return;
	}
	MP4Free(m_values[index]);
	m_values[index] = (u_int8_t*)MP4Malloc(m_valueSizes[index]);
	pFile->ReadBytes(m_values[index], m_valueSizes[index]);
}
示例#6
0
void MP4SdpAtom::Read() 
{
	// read sdp string, length is implicit in size of atom 
	u_int64_t size = GetEnd() - m_pFile->GetPosition();
	char* data = (char*)MP4Malloc(size + 1);
	ASSERT(data != NULL);
	m_pFile->ReadBytes((u_int8_t*)data, size);
	data[size] = '\0';
	((MP4StringProperty*)m_pProperties[0])->SetValue(data);
	MP4Free(data);
}
示例#7
0
void MP4StringProperty::Read(MP4File* pFile, u_int32_t index)
{
	if (m_implicit) {
		return;
	}
	if (m_useCountedFormat) {
		m_values[index] = pFile->ReadCountedString(
			(m_useUnicode ? 2 : 1), m_useExpandedCount);
	} else if (m_fixedLength) {
		MP4Free(m_values[index]);
		m_values[index] = (char*)MP4Calloc(m_fixedLength + 1);
		pFile->ReadBytes((u_int8_t*)m_values[index], m_fixedLength);
	} else {
		m_values[index] = pFile->ReadString();
	}
}
示例#8
0
void MP4StringProperty::SetValue(const char* value, u_int32_t index) 
{
	if (m_readOnly) {
		throw new MP4Error(EACCES, "property is read-only", m_name);
	}

	MP4Free(m_values[index]);

	if (m_fixedLength) {
		m_values[index] = (char*)MP4Calloc(m_fixedLength + 1);
		if (value) {
			strncpy(m_values[index], value, m_fixedLength);
		}
	} else {
		if (value) {
			m_values[index] = MP4Stralloc(value);
		} else {
			m_values[index] = NULL;
		}
	}
}
示例#9
0
void MP4Track::ReadChunk(MP4ChunkId chunkId, 
	u_int8_t** ppChunk, u_int32_t* pChunkSize)
{
	ASSERT(chunkId);
	ASSERT(ppChunk);
	ASSERT(pChunkSize);

	u_int64_t chunkOffset = 
		m_pChunkOffsetProperty->GetValue(chunkId - 1);

	*pChunkSize = GetChunkSize(chunkId);
	*ppChunk = (u_int8_t*)MP4Malloc(*pChunkSize);

	VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
		printf("ReadChunk: track %u id %u offset 0x"LLX" size %u (0x%x)\n",
			m_trackId, chunkId, chunkOffset, *pChunkSize, *pChunkSize));

	u_int64_t oldPos = m_pFile->GetPosition(); // only used in mode == 'w'
	try {
		m_pFile->SetPosition(chunkOffset);
		m_pFile->ReadBytes(*ppChunk, *pChunkSize);
	}
	catch (MP4Error* e) {
		// let's not leak memory
		MP4Free(*ppChunk);
		*ppChunk = NULL;

		if (m_pFile->GetMode() == 'w') {
			m_pFile->SetPosition(oldPos);
		}
		throw e;
	}

	if (m_pFile->GetMode() == 'w') {
		m_pFile->SetPosition(oldPos);
	}
}
示例#10
0
extern "C" char* MP4Info(
	MP4FileHandle mp4File,
	MP4TrackId trackId)
{
	char* info = NULL;

	if (MP4_IS_VALID_FILE_HANDLE(mp4File)) {
		try {
			if (trackId == MP4_INVALID_TRACK_ID) {
			  uint buflen = 4 * 1024;
				info = (char*)MP4Calloc(buflen);

				buflen -= snprintf(info, buflen,
						"Track\tType\tInfo\n");

				u_int32_t numTracks = MP4GetNumberOfTracks(mp4File);

				for (u_int32_t i = 0; i < numTracks; i++) {
					trackId = MP4FindTrackId(mp4File, i);
					char* trackInfo = PrintTrackInfo(mp4File, trackId);
					strncat(info, trackInfo, buflen);
					uint newlen = wcslen(trackInfo);
					if (newlen > buflen) buflen = 0;
					else buflen -= newlen;
					MP4Free(trackInfo);
				}
			} else {
				info = PrintTrackInfo(mp4File, trackId);
			}
		}
		catch (MP4Error* e) {
			delete e;
		}
	}

	return info;
}
示例#11
0
MP4Track::~MP4Track()
{
	MP4Free(m_pCachedReadSample);
	MP4Free(m_pChunkBuffer);
}
示例#12
0
void MP4File::Make3GPCompliant(const char* fileName,  char* majorBrand, u_int32_t minorVersion, char** supportedBrands, u_int32_t supportedBrandsCount, bool deleteIodsAtom)
{
    char brand[5] = "3gp5";
    char* _3gpSupportedBrands[1] = { (char*)&brand };

    if (majorBrand) {
        if (!supportedBrands || !supportedBrandsCount) {
            throw new MP4Error("Invalid parameters", "MP4File::Make3GPCompliant");
        }
    }

    m_fileName = MP4Stralloc(fileName);
    m_mode = 'r';
    // first load meta-info into memory
    Open("rb");
    ReadFromFile();

    CacheProperties();	// of moov atom

    // now switch over to writing the new file
    MP4Free(m_fileName);
    // create a temporary file
    m_fileName = MP4Stralloc(TempFileName());

    MakeFtypAtom(
        majorBrand ? majorBrand : (char*)brand,
        majorBrand ? minorVersion  : _3GP_MINOR_VERSION,
        majorBrand ? supportedBrands : (char**)_3gpSupportedBrands,
        majorBrand ? supportedBrandsCount : 1);

    if (deleteIodsAtom) {
        // Delete the iods atom, if it exists....
        MP4Atom* iodsAtom = m_pRootAtom->FindAtom("moov.iods");
        if (iodsAtom) {
            MP4Atom* moovAtom = m_pRootAtom->FindAtom("moov");
            ASSERT(moovAtom);

            moovAtom->DeleteChildAtom(iodsAtom);
        }
    }


    FILE* pReadFile = m_pFile;
    m_pFile = NULL;
    m_mode = 'w';

    Open("wb");

    SetIntegerProperty("moov.mvhd.modificationTime",
                       MP4GetAbsTimestamp());

    // writing meta info in the optimal order
    ((MP4RootAtom*)m_pRootAtom)->BeginOptimalWrite();

    // write data in optimal order
    RewriteMdat(pReadFile, m_pFile);

    // finish writing
    ((MP4RootAtom*)m_pRootAtom)->FinishOptimalWrite();

    // cleanup
    fclose(m_pFile);
    m_pFile = NULL;
    fclose(pReadFile);

    // move temporary file into place
    Rename(m_fileName, fileName);
}
示例#13
0
  /*! \brief Read property from file.
  
      \param pFile                input, file handle.
      \param index                input, index to read.
  */
	void Read(MP4File* pFile, u_int32_t index = 0) {
	  MP4Free(m_values[index]);
	  m_values[index] = (char*)MP4Calloc(m_fixedLength + 1);
	  (void)pFile->ReadBytes((u_int8_t*)m_values[index], m_fixedLength);
  }
示例#14
0
bool LoadFileAAC(FILE_INFO *pFile)
{
    MP4FileHandle h = MP4Read(GetFullPath(pFile), 0);
    if (h == MP4_INVALID_FILE_HANDLE) {
		return false;
	}
	char* value;
	char* buff;
	u_int16_t no, total;
	if (MP4GetMetadataName(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetTrackNameSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataArtist(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetArtistNameSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataWriter(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetComposerSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataComment(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetCommentSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataTool(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetSoftwareSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataYear(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetYearSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataAlbum(h, &value) == true) {
		if (UTF8toSJIS(value, &buff) == true) {
			SetAlbumNameSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataAlbumArtist(h, &value) == true) { /* 取得できるようにmp4v2.dllを変更 */
		if (UTF8toSJIS(value, &buff) == true) {
			SetAlbumArtistSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataTrack(h, &no, &total) == true) {
		char trackNo[10];
		if (total > 0) {
			sprintf(trackNo, "%d/%d", no, total);
		} else {
			sprintf(trackNo, "%d", no);
		}
		SetTrackNumberSI(pFile, trackNo);
	}
	if (MP4GetMetadataDisk(h, &no, &total) == true) {
		char diskNo[10];
		if (total > 0) {
			sprintf(diskNo, "%d/%d", no, total);
		} else {
			sprintf(diskNo, "%d", no);
		}
		SetDiskNumberSI(pFile, diskNo);
	}
	if (MP4GetMetadataGenre(h, &value) == true) { /* 取得できるようにmp4v2.dllを変更 */
		if (UTF8toSJIS(value, &buff) == true) {
			SetGenreSI(pFile, buff);
			free(buff);
		}
	}
	if (MP4GetMetadataGrouping(h, &value) == true) { /* 取得できるようにmp4v2.dllに追加 */
		if (UTF8toSJIS(value, &buff) == true) {
			SetKeywordSI(pFile, buff);
			free(buff);
		}
	}
	CString strOther = "";
	{
		u_int16_t tempo;
		if (MP4GetMetadataTempo(h, &tempo) == true) {
			if (tempo > 0) {
				char buff[10];
				sprintf(buff, " %dBPM", tempo);
				strOther += buff;
			}
		}
	}
	{
		u_int8_t cpl;
		if (MP4GetMetadataCompilation(h, &cpl) == true) {
			if (cpl == 1) {
				strOther += " コンピレーションの一部";
			}
		}
	}

	//MP4TrackId trackId = MP4FindTrackId(pFile, 0, MP4_AUDIO_TRACK_TYPE);
	//SetAudioFormat(pFile, MP4Info(h));
	// mp4info.cpp PrintAudioInfo()
	MP4TrackId trackId = MP4FindTrackId(h, 0);
	static const char* mpeg4AudioNames[] = {
		"MPEG-4 AAC main",
		"MPEG-4 AAC LC", 
		"MPEG-4 AAC SSR",
		"MPEG-4 AAC LTP",
		NULL,
		"MPEG-4 AAC Scalable",
		"MPEG-4 TwinVQ",
		"MPEG-4 CELP",
		"MPEG-4 HVXC",
		NULL, NULL,
		"MPEG-4 TTSI",
		"MPEG-4 Main Synthetic",
		"MPEG-4 Wavetable Syn",
		"MPEG-4 General MIDI",
		"MPEG-4 Algo Syn and Audio FX",
		"MPEG-4 ER AAC LC",
		NULL,
		"MPEG-4 ER AAC LTP",
		"MPEG-4 ER AAC Scalable",
		"MPEG-4 ER TwinVQ",
		"MPEG-4 ER BSAC",
		"MPEG-4 ER ACC LD",
		"MPEG-4 ER CELP",
		"MPEG-4 ER HVXC",
		"MPEG-4 ER HILN",
		"MPEG-4 ER Parametric",
	};
	static u_int8_t mpegAudioTypes[] = {
		MP4_MPEG2_AAC_MAIN_AUDIO_TYPE,	// 0x66
		MP4_MPEG2_AAC_LC_AUDIO_TYPE,	// 0x67
		MP4_MPEG2_AAC_SSR_AUDIO_TYPE,	// 0x68
		MP4_MPEG2_AUDIO_TYPE,			// 0x69
		MP4_MPEG1_AUDIO_TYPE,			// 0x6B
		MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE,
		MP4_VORBIS_AUDIO_TYPE,
		MP4_ALAW_AUDIO_TYPE,
		MP4_ULAW_AUDIO_TYPE,
		MP4_G723_AUDIO_TYPE,
		MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE,
	};
	static const char* mpegAudioNames[] = {
		"MPEG-2 AAC Main",
		"MPEG-2 AAC LC",
		"MPEG-2 AAC SSR",
		"MPEG-2 Audio (13818-3)",
		"MPEG-1 Audio (11172-3)",
		"PCM16 (little endian)",
		"Vorbis",
		"G.711 aLaw",
		"G.711 uLaw",
		"G.723.1",
		"PCM16 (big endian)",
	};
	static u_int8_t numMpegAudioTypes = 
		sizeof(mpegAudioTypes) / sizeof(u_int8_t);

	u_int8_t type =
		MP4GetTrackEsdsObjectTypeId(h, trackId);
	const char* typeName = "Unknown";

	if (type == MP4_MPEG4_AUDIO_TYPE) {
	  u_int8_t* pAacConfig = NULL;
	  u_int32_t aacConfigLength;

	  MP4GetTrackESConfiguration(h, 
				     trackId,
				     &pAacConfig,
				     &aacConfigLength);

	  if (pAacConfig != NULL && aacConfigLength >= 2) {
	    type = (pAacConfig[0] >> 3) & 0x1f;
	    if (type == 0 || type == 5 || type == 10 || type == 11 ||
		type == 18 || type >= 28) {
	      typeName = "MPEG-4";
	    } else {
	        typeName = mpeg4AudioNames[type - 1];
	    }
	    MP4Free(pAacConfig);
	  } else {
示例#15
0
void MP4File::MakeIsmaCompliant(bool addIsmaComplianceSdp)
{
    ProtectWriteOperation("MP4MakeIsmaCompliant");

    if (m_useIsma) {
        // already done
        return;
    }
    m_useIsma = true;

    // find first audio and/or video tracks

    MP4TrackId audioTrackId = MP4_INVALID_TRACK_ID;
    try {
        audioTrackId = FindTrackId(0, MP4_AUDIO_TRACK_TYPE);
    }
    catch (MP4Error* e) {
        delete e;
    }

    MP4TrackId videoTrackId = MP4_INVALID_TRACK_ID;
    try {
        videoTrackId = FindTrackId(0, MP4_VIDEO_TRACK_TYPE);
    }
    catch (MP4Error* e) {
        delete e;
    }

    u_int64_t fileMsDuration =
        ConvertFromMovieDuration(GetDuration(), MP4_MSECS_TIME_SCALE);

    // delete any existing OD track
    if (m_odTrackId != MP4_INVALID_TRACK_ID) {
        DeleteTrack(m_odTrackId);
    }

    AddODTrack();
    SetODProfileLevel(0xFF);

    if (audioTrackId != MP4_INVALID_TRACK_ID) {
        AddTrackToOd(audioTrackId);
    }

    if (videoTrackId != MP4_INVALID_TRACK_ID) {
        AddTrackToOd(videoTrackId);
    }

    // delete any existing scene track
    MP4TrackId sceneTrackId = MP4_INVALID_TRACK_ID;
    try {
        sceneTrackId = FindTrackId(0, MP4_SCENE_TRACK_TYPE);
    }
    catch (MP4Error *e) {
        delete e;
    }
    if (sceneTrackId != MP4_INVALID_TRACK_ID) {
        DeleteTrack(sceneTrackId);
    }

    // add scene track
    sceneTrackId = AddSceneTrack();
    SetSceneProfileLevel(0xFF);
    SetGraphicsProfileLevel(0xFF);
    SetTrackIntegerProperty(sceneTrackId,
                            "mdia.minf.stbl.stsd.mp4s.esds.decConfigDescr.objectTypeId",
                            MP4SystemsV2ObjectType);

    SetTrackESConfiguration(sceneTrackId,
                            BifsV2Config, sizeof(BifsV2Config));

    u_int8_t* pBytes = NULL;
    u_int64_t numBytes = 0;

    // write OD Update Command
    CreateIsmaODUpdateCommandFromFileForFile(
        m_odTrackId,
        audioTrackId,
        videoTrackId,
        &pBytes,
        &numBytes);

    WriteSample(m_odTrackId, pBytes, numBytes, fileMsDuration);

    MP4Free(pBytes);
    pBytes = NULL;

    // write BIFS Scene Replace Command
    CreateIsmaSceneCommand(
        MP4_IS_VALID_TRACK_ID(audioTrackId),
        MP4_IS_VALID_TRACK_ID(videoTrackId),
        &pBytes,
        &numBytes);

    WriteSample(sceneTrackId, pBytes, numBytes, fileMsDuration);

    MP4Free(pBytes);
    pBytes = NULL;

    // add session level sdp
    CreateIsmaIodFromFile(
        m_odTrackId,
        sceneTrackId,
        audioTrackId,
        videoTrackId,
        &pBytes,
        &numBytes);

    char* iodBase64 = MP4ToBase64(pBytes, numBytes);

    char* sdpBuf = (char*)MP4Calloc(strlen(iodBase64) + 256);

    if (addIsmaComplianceSdp) {
        strcpy(sdpBuf, "a=isma-compliance:1,1.0,1\015\012");
    }

    sprintf(&sdpBuf[strlen(sdpBuf)],
            "a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042\015\012",
            iodBase64);

    SetSessionSdp(sdpBuf);

    VERBOSE_ISMA(GetVerbosity(),
                 printf("IOD SDP = %s\n", sdpBuf));

    MP4Free(iodBase64);
    iodBase64 = NULL;
    MP4Free(pBytes);
    pBytes = NULL;
    MP4Free(sdpBuf);
    sdpBuf = NULL;
}
示例#16
0
void MP4File::CreateIsmaIodFromParams(
    u_int8_t videoProfile,
    u_int32_t videoBitrate,
    u_int8_t* videoConfig,
    u_int32_t videoConfigLength,
    u_int8_t audioProfile,
    u_int32_t audioBitrate,
    u_int8_t* audioConfig,
    u_int32_t audioConfigLength,
    u_int8_t** ppIodBytes,
    u_int64_t* pIodNumBytes)
{
    MP4IntegerProperty* pInt;
    u_int8_t* pBytes = NULL;
    u_int64_t numBytes;

    // Create the IOD
    MP4Descriptor* pIod = new MP4IODescriptor();
    pIod->SetTag(MP4IODescrTag);
    pIod->Generate();

    // Set audio and video profileLevels
    pIod->FindProperty("audioProfileLevelId",
                       (MP4Property**)&pInt);
    pInt->SetValue(audioProfile);

    pIod->FindProperty("visualProfileLevelId",
                       (MP4Property**)&pInt);
    pInt->SetValue(videoProfile);

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

    // Add ES Descriptors

    // Scene
    CreateIsmaSceneCommand(
        (audioProfile != 0xFF),
        (videoProfile != 0xFF),
        &pBytes,
        &numBytes);

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

    char* sceneCmdBase64 = MP4ToBase64(pBytes, numBytes);

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

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

    /* MP4Descriptor* pSceneEsd = */
    CreateESD(
        pEsProperty,
        201,				// esid
        MP4SystemsV2ObjectType,
        MP4SceneDescriptionStreamType,
        numBytes,			// bufferSize
        numBytes * 8,		// bitrate
        BifsV2Config,
        sizeof(BifsV2Config),
        urlBuf);

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

    // OD

    // Video
    MP4DescriptorProperty* pVideoEsdProperty =
        new MP4DescriptorProperty();
    pVideoEsdProperty->SetTags(MP4ESDescrTag);

    /* MP4Descriptor* pVideoEsd = */
    CreateESD(
        pVideoEsdProperty,
        20,					// esid
        MP4_MPEG4_VIDEO_TYPE,
        MP4VisualStreamType,
        videoBitrate / 8,	// bufferSize
        videoBitrate,
        videoConfig,
        videoConfigLength,
        NULL);

    // Audio
    MP4DescriptorProperty* pAudioEsdProperty =
        new MP4DescriptorProperty();
    pAudioEsdProperty->SetTags(MP4ESDescrTag);

    /* MP4Descriptor* pAudioEsd = */
    CreateESD(
        pAudioEsdProperty,
        10,					// esid
        MP4_MPEG4_AUDIO_TYPE,
        MP4AudioStreamType,
        audioBitrate / 8, 	// bufferSize
        audioBitrate,
        audioConfig,
        audioConfigLength,
        NULL);

    CreateIsmaODUpdateCommandForStream(
        pAudioEsdProperty,
        pVideoEsdProperty,
        &pBytes,
        &numBytes);

    // cleanup temporary descriptor properties
    delete pAudioEsdProperty;
    delete pVideoEsdProperty;

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

    char* odCmdBase64 = MP4ToBase64(pBytes, numBytes);

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

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

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

    /* MP4Descriptor* pOdEsd = */
    CreateESD(
        pEsProperty,
        101,
        MP4SystemsV1ObjectType,
        MP4ObjectDescriptionStreamType,
        numBytes,		// bufferSize
        numBytes * 8,	// bitrate
        NULL,			// config
        0,				// configLength
        urlBuf);

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

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

    delete pIod;

    VERBOSE_ISMA(GetVerbosity(),
                 printf("IOD data =\n"); MP4HexDump(*ppIodBytes, *pIodNumBytes));
}
示例#17
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));
}
示例#18
0
//
// Clone - clone my properties to destination atom
//
// this method simplifies duplicating avcC atom properties from
// source to destination file using a single API rather than
// having to copy each property.  This API encapsulates the object
// so the application layer need not concern with each property
// thereby isolating any future changes to atom properties.
//
// ----------------------------------------
// property   description
// ----------------------------------------
//
// 0    configurationVersion
// 1    AVCProfileIndication
// 2    profile_compatibility
// 3    AVCLevelIndication
// 4    reserved
// 5    lengthSizeMinusOne
// 6    reserved
// 7    number of SPS
// 8    SPS entries
// 9    number of PPS
// 10   PPS entries
//
//
void MP4HvcCAtom::Clone(MP4HvcCAtom *dstAtom)
{
#if 1 //cwm
    MP4Property *dstProperty;
    MP4TableProperty *pTable;
    uint16_t i16;
    uint64_t i32;
    uint64_t i64;
    uint8_t *tmp;

    // source pointer Property I16
    MP4Integer16Property *spPI16;
    // source pointer Property Bytes
    MP4BytesProperty *spPB;

    // dest pointer Property I16
    MP4Integer16Property *dpPI16;
    // dest pointer Property Bytes
    MP4BytesProperty *dpPB;


    // start with defaults and reserved fields
    dstAtom->Generate();

    // 0, 4, 6 are now generated from defaults
    // leaving 1, 2, 3, 5, 7, 8, 9, 10 to export

    dstProperty=dstAtom->GetProperty(1);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        0x12);//((MP4Integer8Property *)m_pProperties[1])->GetValue()

    dstProperty=dstAtom->GetProperty(2);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        0x34);//((MP4Integer8Property *)m_pProperties[2])->GetValue()

    dstProperty=dstAtom->GetProperty(3);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        ((MP4Integer8Property *)m_pProperties[3])->GetValue());

    dstProperty=dstAtom->GetProperty(5);
    ((MP4BitfieldProperty *)dstProperty)->SetValue(
        ((MP4BitfieldProperty *)m_pProperties[5])->GetValue());

    //
    // 7 and 8 are related SPS (one set of sequence parameters)
    //
    // first the count bitfield
    //
    dstProperty=dstAtom->GetProperty(7);
    dstProperty->SetReadOnly(false);
    ((MP4BitfieldProperty *)dstProperty)->SetValue(
        ((MP4BitfieldProperty *)m_pProperties[7])->GetValue());
    dstProperty->SetReadOnly(true);

    // next export SPS Length and NAL bytes */

    // first source pointers
    pTable = (MP4TableProperty *) m_pProperties[8];
    spPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    spPB = (MP4BytesProperty *)pTable->GetProperty(1);

    // now dest pointers
    dstProperty=dstAtom->GetProperty(8);
    pTable = (MP4TableProperty *) dstProperty;
    dpPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    dpPB = (MP4BytesProperty *)pTable->GetProperty(1);

    // sps length
    i16 = spPI16->GetValue();
    i64 = i16;
    // FIXME - this leaves m_maxNumElements =2
    // but src atom m_maxNumElements is 1
    dpPI16->InsertValue(i64, 0);

    // export byte array
    i32 = i16;
    // copy bytes to local buffer
    tmp = (uint8_t *)MP4Malloc(i32);
    ASSERT(tmp != NULL);
    spPB->CopyValue(tmp, 0);
    // set element count
    dpPB->SetCount(1);
    // copy bytes
    dpPB->SetValue(tmp, i32, 0);
    MP4Free((void *)tmp);

    //
    // 9 and 10 are related PPS (one set of picture parameters)
    //
    // first the integer8 count
    //
    dstProperty=dstAtom->GetProperty(9);
    dstProperty->SetReadOnly(false);
    ((MP4Integer8Property *)dstProperty)->SetValue(
        ((MP4Integer8Property *)m_pProperties[9])->GetValue());
    dstProperty->SetReadOnly(true);

    // next export PPS Length and NAL bytes */

    // first source pointers
    pTable = (MP4TableProperty *) m_pProperties[10];
    spPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    spPB = (MP4BytesProperty *)pTable->GetProperty(1);

    // now dest pointers
    dstProperty=dstAtom->GetProperty(10);
    pTable = (MP4TableProperty *) dstProperty;
    dpPI16 = (MP4Integer16Property *)pTable->GetProperty(0);
    dpPB = (MP4BytesProperty *)pTable->GetProperty(1);
#if 1//cwm 500
    // pps length
    i16 = spPI16->GetValue();
    i64 = i16;
    dpPI16->InsertValue(i64, 0);

    // export byte array
    i32 = i16;
    // copy bytes to local buffer
    tmp = (uint8_t *)MP4Malloc(i32);
    ASSERT(tmp != NULL);
    spPB->CopyValue(tmp, 0);
    // set element count
    dpPB->SetCount(1);
    // copy bytes
    dpPB->SetValue(tmp, i32, 0);
    MP4Free((void *)tmp);
#endif //cwm 500
#endif //cwm
}
示例#19
0
ALACSource::ALACSource(const std::shared_ptr<FILE> &fp)
    : m_position(0), m_fp(fp)
{
    try {
        int fd = fileno(m_fp.get());
        {
            util::FilePositionSaver _(fd);
            _lseeki64(fd, 0, SEEK_SET);
            char buf[8];
            if (read(fd, buf, 8) != 8 || std::memcmp(&buf[4], "ftyp", 4))
                throw std::runtime_error("Not an MP4 file");
        }
        static MP4FDReadProvider provider;
        std::string name = strutil::format("%d", fd);
        m_file.Read(name.c_str(), &provider);
        m_track_id = m_file.FindTrackId(0, MP4_AUDIO_TRACK_TYPE);
        const char *type = m_file.GetTrackMediaDataName(m_track_id);
        if (std::strcmp(type, "alac"))
            throw std::runtime_error("Not an ALAC file");

        const char *alacprop, *chanprop;
        const char *brand = m_file.GetStringProperty("ftyp.majorBrand");
        if (!std::strcmp(brand, "qt  ")) {
            // throw std::runtime_error("Not supported format");
            alacprop = "mdia.minf.stbl.stsd.alac.wave.alac.decoderConfig";
            chanprop = "mdia.minf.stbl.stsd.alac.wave.chan.data";
        } else {
            alacprop = "mdia.minf.stbl.stsd.alac.alac.decoderConfig";
            chanprop = "mdia.minf.stbl.stsd.alac.chan.data";
        }

        std::vector<uint8_t> alac, chan;
        uint8_t *value;
        uint32_t size;
        m_file.GetTrackBytesProperty(m_track_id, alacprop, &value, &size);
        std::copy(value + 4, value + size, std::back_inserter(alac));
        MP4Free(value);
        value = 0;
        try {
            m_file.GetTrackBytesProperty(m_track_id, chanprop, &value, &size);
            std::copy(value + 4, value + size, std::back_inserter(chan));
            MP4Free(value);
        } catch (...) {}
        if (alac.size() != 24 || (chan.size() && chan.size() < 12))
            throw std::runtime_error("ALACSource: invalid magic cookie");

        uint32_t timeScale;
        std::memcpy(&timeScale, &alac[20], 4);
        timeScale = util::b2host32(timeScale);
        m_asbd = cautil::buildASBDForPCM(timeScale, alac[9], alac[5],
                                    kAudioFormatFlagIsSignedInteger,
                                    kAudioFormatFlagIsAlignedHigh);
        m_oasbd = cautil::buildASBDForPCM2(timeScale, alac[9], alac[5],
                                           32, kAudioFormatFlagIsSignedInteger);

        m_buffer.units_per_packet = m_asbd.mBytesPerFrame;

        AudioChannelLayout acl = { 0 };
        if (chan.size()) {
            util::fourcc tag(reinterpret_cast<const char*>(&chan[0]));
            util::fourcc bitmap(reinterpret_cast<const char*>(&chan[4]));
            acl.mChannelLayoutTag = tag;
            acl.mChannelBitmap = bitmap;
            chanmap::getChannels(&acl, &m_chanmap);
        }
        m_decoder = std::shared_ptr<ALACDecoder>(new ALACDecoder());
        CHECKCA(m_decoder->Init(&alac[0], alac.size()));
        m_length = m_file.GetTrackDuration(m_track_id);

        mp4a::fetchTags(m_file, &m_tags);
    } catch (mp4v2::impl::Exception *e) {
        handle_mp4error(e);
    }
}
示例#20
0
ALACSource::ALACSource(const std::wstring &path)
    : m_position(0)
{
    try {
	m_file.Read(w2m(path, utf8_codecvt_facet()).c_str(), 0);
	m_track_id = m_file.FindTrackId(0, MP4_AUDIO_TRACK_TYPE);
	const char *type = m_file.GetTrackMediaDataName(m_track_id);
	if (std::strcmp(type, "alac"))
	    throw std::runtime_error("Not an ALAC file");

	const char *alacprop, *chanprop;
	const char *brand = m_file.GetStringProperty("ftyp.majorBrand");
	if (!std::strcmp(brand, "qt  ")) {
	    // throw std::runtime_error("Not supported format");
	    alacprop = "mdia.minf.stbl.stsd.alac.wave.alac.decoderConfig";
	    chanprop = "mdia.minf.stbl.stsd.alac.wave.chan.data";
	} else {
	    alacprop = "mdia.minf.stbl.stsd.alac.alac.decoderConfig";
	    chanprop = "mdia.minf.stbl.stsd.alac.chan.data";
	}

	std::vector<uint8_t> alac, chan;
	uint8_t *value;
	uint32_t size;
	m_file.GetTrackBytesProperty(m_track_id, alacprop, &value, &size);
	std::copy(value + 4, value + size, std::back_inserter(alac));
	MP4Free(value);
	value = 0;
	try {
	    m_file.GetTrackBytesProperty(m_track_id, chanprop, &value, &size);
	    std::copy(value + 4, value + size, std::back_inserter(chan));
	    MP4Free(value);
	} catch (...) {}
	if (alac.size() != 24 || (chan.size() && chan.size() < 12))
	    throw std::runtime_error("ALACSource: invalid magic cookie");

	std::memset(&m_format, 0, sizeof m_format);
	m_format.m_type = SampleFormat::kIsSignedInteger;
	m_format.m_endian = SampleFormat::kIsLittleEndian;
	m_format.m_nchannels = alac[9];
	m_format.m_bitsPerSample = alac[5];
	if (m_format.m_bitsPerSample == 20)
	    m_format.m_bitsPerSample = 24;
	uint32_t timeScale;
	std::memcpy(&timeScale, &alac[20], 4);
	timeScale = b2host32(timeScale);
	m_format.m_rate = timeScale;

	AudioChannelLayout acl = { 0 };
	if (chan.size()) {
	    fourcc tag(reinterpret_cast<const char*>(&chan[0]));
	    fourcc bitmap(reinterpret_cast<const char*>(&chan[4]));
	    acl.mChannelLayoutTag = tag;
	    acl.mChannelBitmap = bitmap;
	    chanmap::GetChannels(&acl, &m_chanmap);
	}
	m_decoder = x::shared_ptr<ALACDecoder>(new ALACDecoder());
	CHECKCA(m_decoder->Init(&alac[0], alac.size()));
	setRange(0, m_file.GetTrackDuration(m_track_id));

	mp4a::fetchTags(m_file, &m_tags);
    } catch (mp4v2::impl::Exception *e) {
	handle_mp4error(e);
    }
}
示例#21
0
void MP4RtpHintTrack::ReadPacket(
	u_int16_t packetIndex,
	u_int8_t** ppBytes, 
	u_int32_t* pNumBytes,
	u_int32_t ssrc,
	bool addHeader,
	bool addPayload)
{
	if (m_pReadHint == NULL) {
		throw new MP4Error("no hint has been read",
			"MP4ReadRtpPacket");
	}
	if (!addHeader && !addPayload) {
		throw new MP4Error("no data requested",
			"MP4ReadRtpPacket");
	}

	MP4RtpPacket* pPacket =
		m_pReadHint->GetPacket(packetIndex);

	*pNumBytes = 0;
	if (addHeader) {
		*pNumBytes += 12;
	}
	if (addPayload) {
		*pNumBytes += pPacket->GetDataSize();
	}

	// if needed, allocate the packet memory
	bool buffer_malloc = false;

	if (*ppBytes == NULL) {
		*ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
		buffer_malloc = true;
	}

	try {
		u_int8_t* pDest = *ppBytes;

		if (addHeader) {
			*pDest++ =
				0x80 | (pPacket->GetPBit() << 5) | (pPacket->GetXBit() << 4);

			*pDest++ =
				(pPacket->GetMBit() << 7) | pPacket->GetPayload();

			*((u_int16_t*)pDest) = 
				htons(m_rtpSequenceStart + pPacket->GetSequenceNumber());
			pDest += 2; 

			*((u_int32_t*)pDest) = 
				htonl(m_rtpTimestampStart + (u_int32_t)m_readHintTimestamp);
			pDest += 4; 

			*((u_int32_t*)pDest) = 
				htonl(ssrc);
			pDest += 4;
		}

		if (addPayload) {
			pPacket->GetData(pDest);
		}
	}
	catch (MP4Error* e) {
		if (buffer_malloc) {
			MP4Free(*ppBytes);
			*ppBytes = NULL;
		}
		throw e;
	}

	VERBOSE_READ_HINT(m_pFile->GetVerbosity(),
		printf("ReadPacket: %u ", packetIndex);
		MP4HexDump(*ppBytes, *pNumBytes););
示例#22
0
void MP4Track::ReadSample(
	MP4SampleId sampleId,
	u_int8_t** ppBytes, 
	u_int32_t* pNumBytes, 
	MP4Timestamp* pStartTime, 
	MP4Duration* pDuration,
	MP4Duration* pRenderingOffset, 
	bool* pIsSyncSample)
{
	if (sampleId == MP4_INVALID_SAMPLE_ID) {
		throw new MP4Error("sample id can't be zero", 
			"MP4Track::ReadSample");
	}

	// handle unusual case of wanting to read a sample
	// that is still sitting in the write chunk buffer
	if (m_pChunkBuffer && sampleId >= m_writeSampleId - m_chunkSamples) {
		WriteChunkBuffer();
	}

	FILE* pFile = GetSampleFile(sampleId);

	if (pFile == (FILE*)-1) {
		throw new MP4Error("sample is located in an inaccessible file",
			"MP4Track::ReadSample");
	}

	u_int64_t fileOffset = GetSampleFileOffset(sampleId);

	u_int32_t sampleSize = GetSampleSize(sampleId);
	if (*ppBytes != NULL && *pNumBytes < sampleSize) {
		throw new MP4Error("sample buffer is too small",
			 "MP4Track::ReadSample");
	}
	*pNumBytes = sampleSize;

	VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
		printf("ReadSample: track %u id %u offset 0x"LLX" size %u (0x%x)\n",
			m_trackId, sampleId, fileOffset, *pNumBytes, *pNumBytes));

	bool bufferMalloc = false;
	if (*ppBytes == NULL) {
		*ppBytes = (u_int8_t*)MP4Malloc(*pNumBytes);
		bufferMalloc = true;
	}

	u_int64_t oldPos = m_pFile->GetPosition(pFile); // only used in mode == 'w'
	try { 
		m_pFile->SetPosition(fileOffset, pFile);
		m_pFile->ReadBytes(*ppBytes, *pNumBytes, pFile);

		if (pStartTime || pDuration) {
			GetSampleTimes(sampleId, pStartTime, pDuration);

			VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
				printf("ReadSample:  start "LLU" duration "LLD"\n",
					(pStartTime ? *pStartTime : 0), 
					(pDuration ? *pDuration : 0)));
		}
		if (pRenderingOffset) {
			*pRenderingOffset = GetSampleRenderingOffset(sampleId);

			VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
				printf("ReadSample:  renderingOffset "LLD"\n",
					*pRenderingOffset));
		}
		if (pIsSyncSample) {
			*pIsSyncSample = IsSyncSample(sampleId);

			VERBOSE_READ_SAMPLE(m_pFile->GetVerbosity(),
				printf("ReadSample:  isSyncSample %u\n",
					*pIsSyncSample));
		}
	}

	catch (MP4Error* e) {
		if (bufferMalloc) {
			// let's not leak memory
			MP4Free(*ppBytes);
			*ppBytes = NULL;
		}
		if (m_pFile->GetMode() == 'w') {
			m_pFile->SetPosition(oldPos, pFile);
		}
		throw e;
	}

	if (m_pFile->GetMode() == 'w') {
		m_pFile->SetPosition(oldPos, pFile);
	}
}
示例#23
0
/** Action for exporting chapters from the <b>job.file</b>
 *
 *  
 *  @param job the job to process
 *  @return mp4v2::util::SUCCESS if successful, mp4v2::util::FAILURE otherwise
 */
bool
ChapterUtility::actionExport( JobContext& job )
{
    job.fileHandle = MP4Read( job.file.c_str() );
    if( job.fileHandle == MP4_INVALID_FILE_HANDLE )
    {
        return herrf( "unable to open for read: %s\n", job.file.c_str() );
    }

    // get the list of chapters
    MP4Chapter_t*  chapters = 0;
    uint32_t       chapterCount = 0;
    MP4ChapterType chtp = MP4GetChapters( job.fileHandle, &chapters, &chapterCount, _ChapterType );
    if (0 == chapterCount)
    {
        return herrf( "File \"%s\" does not contain chapters of type %s\n", job.file.c_str(),
                      getChapterTypeName( chtp ).c_str() );
    }

    // build the filename
    string outName = job.file;
    if( _ChapterFile.empty() )
    {
        FileSystem::pathnameStripExtension( outName );
        outName.append( ".chapters.txt" );
    }
    else
    {
        outName = _ChapterFile;
    }

    ostringstream oss;
    oss << "Exporting " << chapterCount << " " << getChapterTypeName( chtp );
    oss << " chapters from file " << '"' << job.file << '"' << " into chapter file " << '"' << outName << '"' << endl;

    verbose1f( "%s", oss.str().c_str() );
    if( dryrunAbort() )
    {
        // free up the memory
        MP4Free(chapters);

        return SUCCESS;
    }

    // open the file
    File out( outName, File::MODE_CREATE );
    if( openFileForWriting( out ) )
    {
        // free up the memory
        MP4Free(chapters);

        return FAILURE;
    }

    // write the chapters
#if defined( _WIN32 )
    static const char* LINEND = "\r\n";
#else
    static const char* LINEND = "\n";
#endif
    File::Size nout;
    bool failure = SUCCESS;
    int width = 2;
    if( CHPT_FMT_COMMON == _ChapterFormat && (chapterCount / 100) >= 1 )
    {
        width = 3;
    }
    Timecode duration( 0, CHAPTERTIMESCALE );
    duration.setFormat( Timecode::DECIMAL );
    for( uint32_t i = 0; i < chapterCount; ++i )
    {
        // print the infos
        ostringstream oss;
        switch( _ChapterFormat )
        {
            case CHPT_FMT_COMMON:
                oss << "CHAPTER" << setw( width ) << setfill( '0' ) << i+1 <<     '=' << duration.svalue << LINEND
                    << "CHAPTER" << setw( width ) << setfill( '0' ) << i+1 << "NAME=" << chapters[i].title << LINEND;
                break;
            case CHPT_FMT_NATIVE:
            default:
                oss << duration.svalue << ' ' << chapters[i].title << LINEND;
        }

        string str = oss.str();
        if( out.write( str.c_str(), str.size(), nout ) )
        {
            failure = herrf( "write to %s failed: %s\n", outName.c_str(), sys::getLastErrorStr() );
            break;
        }

        // add the duration of this chapter to the sum (the start time of the next chapter)
        duration += Timecode(chapters[i].duration, CHAPTERTIMESCALE);
    }
    out.close();
    if( failure )
    {
        verbose1f( "removing file %s\n", outName.c_str() );
        ::remove( outName.c_str() );
    }

    // free up the memory
    MP4Free(chapters);

    return SUCCESS;
}
示例#24
0
文件: log.cpp 项目: 2php/mp4v2
/**
 * Log a buffer as ascii-hex
 *
 * @param indent the number of spaces to indent the buffer
 *
 * @param verbosity the level of detail the message contains
 *
 * @param pBytes the buffer to log
 *
 * @param numBytes the number of bytes to log
 *
 * @param format the format string to use to process the
 * remaining arguments, where the format + remaining args
 * describe @p pBytes.  The resulting string should not
 * contain a newline.  Only the first 255 characters of the
 * resulting string (not including the NUL terminator) make
 * it to the log callback or stdout.
 */
void
Log::hexDump( uint8_t           indent,
              MP4LogLevel       verbosity_,
              const uint8_t*    pBytes,
              uint32_t          numBytes,
              const char*       format,
              ... )
{
    va_list     ap;

    ASSERT(pBytes || (numBytes == 0));
    ASSERT(format);

    if (verbosity_ > this->_verbosity)
    {
        // We're not set verbose enough to log this
        return;
    }

    // Build the description by processing format and the
    // remaining args.  Since we don't have asprintf, pick
    // an arbitrary length for the string and use snprintf.
    // To save a memory allocation, only do this if there's
    // a non-empty format string or non-zero indent
    char *desc = NULL;
    if (format[0] || indent)
    {
        desc = (char *)MP4Calloc(256 + indent);
        sprintf(desc,"%*c",indent,' ');
        va_start(ap,format);
        vsnprintf(desc + indent,255,format,ap);
        va_end(ap);
    }

    // From here we can use the C++ standard lib classes and
    // build a string for each line
    for (uint32_t i = 0;(i < numBytes);i += 16)
    {
        // ios_base::ate means at end.  With out this desc
        // gets overwritten with each << operation
        ostringstream oneLine(desc ? desc : "",ios_base::ate);

        // Append the byte offset this line starts with as
        // an 8 character, leading 0, hex number.  Leave the
        // fill character set to 0 for the remaining
        // operations
        oneLine << ':' << hex << setw(8) << setfill('0') <<
            std::right << i << setw(0) << setfill(' ') << ": ";

        uint32_t curlen = min((uint32_t)16,numBytes - i);
        const uint8_t *b = pBytes + i;
        uint32_t j;

        for (j = 0;(j < curlen);j++)
        {
            oneLine << hex << setw(2) << setfill('0') << right << static_cast<uint32_t>(b[j]);
            oneLine << setw(0) << setfill(' ') << ' ';
        }

        for (; j < 16; j++)
        {
            oneLine << "   ";
        }

        b = pBytes + i;
        for (j = 0;(j < curlen);j++)
        {
            if (isprint(static_cast<int>(b[j])))
            {
                oneLine << static_cast<char>(b[j]);
            }
            else
            {
                oneLine << '.';
            }
        }

        // We can either call the callback directly or use
        // the Log::printf function.  To call the callback
        // directly, we need a va_list.  (I think) we need
        // and extra function call to build that, so we may
        // as well call Log::printf.  It's going to
        // double-check the verbosity and the callback
        // function pointer, but that seems OK (13-feb-09,
        // dbyron)
        this->printf(verbosity_,"%s",oneLine.str().c_str());
    }

    if (desc)
    {
        MP4Free(desc);
        desc = NULL;
    }
}