📄 mp4file.cpp
字号:
float MP4File::GetTrackVideoFrameRate(MP4TrackId trackId)
{
MP4SampleId numSamples =
GetTrackNumberOfSamples(trackId);
#ifdef _WIN32
int64_t
#else
u_int64_t
#endif
msDuration =
ConvertFromTrackDuration(trackId,
GetTrackDuration(trackId), MP4_MSECS_TIME_SCALE);
if (msDuration == 0) {
return 0.0;
}
return ((double)numSamples / (double)msDuration) * MP4_MSECS_TIME_SCALE;
}
void MP4File::GetTrackESConfiguration(MP4TrackId trackId,
u_int8_t** ppConfig, u_int32_t* pConfigSize)
{
GetTrackBytesProperty(trackId,
"mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo[0].info",
ppConfig, pConfigSize);
}
void MP4File::SetTrackESConfiguration(MP4TrackId trackId,
const u_int8_t* pConfig, u_int32_t configSize)
{
// get a handle on the track decoder config descriptor
MP4DescriptorProperty* pConfigDescrProperty = NULL;
FindProperty(MakeTrackName(trackId,
"mdia.minf.stbl.stsd.*[0].esds.decConfigDescr.decSpecificInfo"),
(MP4Property**)&pConfigDescrProperty);
if (pConfigDescrProperty == NULL) {
// probably trackId refers to a hint track
throw new MP4Error("no such property", "MP4SetTrackESConfiguration");
}
// lookup the property to store the configuration
MP4BytesProperty* pInfoProperty = NULL;
pConfigDescrProperty->FindProperty("decSpecificInfo[0].info",
(MP4Property**)&pInfoProperty);
// configuration being set for the first time
if (pInfoProperty == NULL) {
// need to create a new descriptor to hold it
MP4Descriptor* pConfigDescr =
pConfigDescrProperty->AddDescriptor(MP4DecSpecificDescrTag);
pConfigDescr->Generate();
pConfigDescrProperty->FindProperty(
"decSpecificInfo[0].info",
(MP4Property**)&pInfoProperty);
ASSERT(pInfoProperty);
}
// set the value
pInfoProperty->SetValue(pConfig, configSize);
}
const char* MP4File::GetHintTrackSdp(MP4TrackId hintTrackId)
{
return GetTrackStringProperty(hintTrackId, "udta.hnti.sdp .sdpText");
}
void MP4File::SetHintTrackSdp(MP4TrackId hintTrackId, const char* sdpString)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4SetHintTrackSdp");
}
AddDescendantAtoms(
MakeTrackName(hintTrackId, NULL), "udta.hnti.sdp ");
SetTrackStringProperty(hintTrackId, "udta.hnti.sdp .sdpText", sdpString);
}
void MP4File::AppendHintTrackSdp(MP4TrackId hintTrackId,
const char* sdpFragment)
{
const char* oldSdpString = NULL;
try {
oldSdpString = GetHintTrackSdp(hintTrackId);
}
catch (MP4Error* e) {
delete e;
SetHintTrackSdp(hintTrackId, sdpFragment);
return;
}
char* newSdpString =
(char*)MP4Malloc(strlen(oldSdpString) + strlen(sdpFragment) + 1);
strcpy(newSdpString, oldSdpString);
strcat(newSdpString, sdpFragment);
SetHintTrackSdp(hintTrackId, newSdpString);
MP4Free(newSdpString);
}
void MP4File::GetHintTrackRtpPayload(
MP4TrackId hintTrackId,
char** ppPayloadName,
u_int8_t* pPayloadNumber,
u_int16_t* pMaxPayloadSize)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4GetHintTrackRtpPayload");
}
((MP4RtpHintTrack*)pTrack)->GetPayload(
ppPayloadName, pPayloadNumber, pMaxPayloadSize);
}
void MP4File::SetHintTrackRtpPayload(MP4TrackId hintTrackId,
const char* payloadName, u_int8_t* pPayloadNumber, u_int16_t maxPayloadSize)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4SetHintTrackRtpPayload");
}
u_int8_t payloadNumber;
if (pPayloadNumber && *pPayloadNumber != 0) {
payloadNumber = *pPayloadNumber;
} else {
payloadNumber = AllocRtpPayloadNumber();
if (pPayloadNumber) {
*pPayloadNumber = payloadNumber;
}
}
((MP4RtpHintTrack*)pTrack)->SetPayload(
payloadName, payloadNumber, maxPayloadSize);
}
u_int8_t MP4File::AllocRtpPayloadNumber()
{
MP4Integer32Array usedPayloads;
u_int32_t i;
// collect rtp payload numbers in use by existing tracks
for (i = 0; i < m_pTracks.Size(); i++) {
MP4Atom* pTrakAtom = m_pTracks[i]->GetTrakAtom();
MP4Integer32Property* pPayloadProperty = NULL;
pTrakAtom->FindProperty("trak.udta.hinf.payt.payloadNumber",
(MP4Property**)&pPayloadProperty);
if (pPayloadProperty) {
usedPayloads.Add(pPayloadProperty->GetValue());
}
}
// search dynamic payload range for an available slot
u_int8_t payload;
for (payload = 96; payload < 128; payload++) {
for (i = 0; i < usedPayloads.Size(); i++) {
if (payload == usedPayloads[i]) {
break;
}
}
if (i == usedPayloads.Size()) {
break;
}
}
if (payload >= 128) {
throw new MP4Error("no more available rtp payload numbers",
"AllocRtpPayloadNumber");
}
return payload;
}
MP4TrackId MP4File::GetHintTrackReferenceTrackId(
MP4TrackId hintTrackId)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4GetHintTrackReferenceTrackId");
}
MP4Track* pRefTrack = ((MP4RtpHintTrack*)pTrack)->GetRefTrack();
if (pRefTrack == NULL) {
return MP4_INVALID_TRACK_ID;
}
return pRefTrack->GetId();
}
void MP4File::ReadRtpHint(
MP4TrackId hintTrackId,
MP4SampleId hintSampleId,
u_int16_t* pNumPackets)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track", "MP4ReadRtpHint");
}
((MP4RtpHintTrack*)pTrack)->
ReadHint(hintSampleId, pNumPackets);
}
u_int16_t MP4File::GetRtpHintNumberOfPackets(
MP4TrackId hintTrackId)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4GetRtpHintNumberOfPackets");
}
return ((MP4RtpHintTrack*)pTrack)->GetHintNumberOfPackets();
}
int8_t MP4File::GetRtpPacketBFrame(
MP4TrackId hintTrackId,
u_int16_t packetIndex)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4GetRtpHintBFrame");
}
return ((MP4RtpHintTrack*)pTrack)->GetPacketBFrame(packetIndex);
}
int32_t MP4File::GetRtpPacketTransmitOffset(
MP4TrackId hintTrackId,
u_int16_t packetIndex)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4GetRtpPacketTransmitOffset");
}
return ((MP4RtpHintTrack*)pTrack)->GetPacketTransmitOffset(packetIndex);
}
void MP4File::ReadRtpPacket(
MP4TrackId hintTrackId,
u_int16_t packetIndex,
u_int8_t** ppBytes,
u_int32_t* pNumBytes,
u_int32_t ssrc,
bool includeHeader,
bool includePayload)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track", "MP4ReadPacket");
}
((MP4RtpHintTrack*)pTrack)->ReadPacket(
packetIndex, ppBytes, pNumBytes,
ssrc, includeHeader, includePayload);
}
MP4Timestamp MP4File::GetRtpTimestampStart(
MP4TrackId hintTrackId)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4GetRtpTimestampStart");
}
return ((MP4RtpHintTrack*)pTrack)->GetRtpTimestampStart();
}
void MP4File::SetRtpTimestampStart(
MP4TrackId hintTrackId,
MP4Timestamp rtpStart)
{
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4SetRtpTimestampStart");
}
((MP4RtpHintTrack*)pTrack)->SetRtpTimestampStart(rtpStart);
}
void MP4File::AddRtpHint(MP4TrackId hintTrackId,
bool isBframe, u_int32_t timestampOffset)
{
ProtectWriteOperation("MP4AddRtpHint");
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track", "MP4AddRtpHint");
}
((MP4RtpHintTrack*)pTrack)->AddHint(isBframe, timestampOffset);
}
void MP4File::AddRtpPacket(
MP4TrackId hintTrackId, bool setMbit, int32_t transmitOffset)
{
ProtectWriteOperation("MP4AddRtpPacket");
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track", "MP4AddRtpPacket");
}
((MP4RtpHintTrack*)pTrack)->AddPacket(setMbit, transmitOffset);
}
void MP4File::AddRtpImmediateData(MP4TrackId hintTrackId,
const u_int8_t* pBytes, u_int32_t numBytes)
{
ProtectWriteOperation("MP4AddRtpImmediateData");
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4AddRtpImmediateData");
}
((MP4RtpHintTrack*)pTrack)->AddImmediateData(pBytes, numBytes);
}
void MP4File::AddRtpSampleData(MP4TrackId hintTrackId,
MP4SampleId sampleId, u_int32_t dataOffset, u_int32_t dataLength)
{
ProtectWriteOperation("MP4AddRtpSampleData");
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4AddRtpSampleData");
}
((MP4RtpHintTrack*)pTrack)->AddSampleData(
sampleId, dataOffset, dataLength);
}
void MP4File::AddRtpESConfigurationPacket(MP4TrackId hintTrackId)
{
ProtectWriteOperation("MP4AddRtpESConfigurationPacket");
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4AddRtpESConfigurationPacket");
}
((MP4RtpHintTrack*)pTrack)->AddESConfigurationPacket();
}
void MP4File::WriteRtpHint(MP4TrackId hintTrackId,
MP4Duration duration, bool isSyncSample)
{
ProtectWriteOperation("MP4WriteRtpHint");
MP4Track* pTrack = m_pTracks[FindTrackIndex(hintTrackId)];
if (strcmp(pTrack->GetType(), MP4_HINT_TRACK_TYPE)) {
throw new MP4Error("track is not a hint track",
"MP4WriteRtpHint");
}
((MP4RtpHintTrack*)pTrack)->WriteHint(duration, isSyncSample);
}
u_int64_t MP4File::ConvertFromMovieDuration(
MP4Duration duration,
u_int32_t timeScale)
{
return MP4ConvertTime((u_int64_t)duration,
GetTimeScale(), timeScale);
}
u_int64_t MP4File::ConvertFromTrackTimestamp(
MP4TrackId trackId,
MP4Timestamp timeStamp,
u_int32_t timeScale)
{
return MP4ConvertTime((u_int64_t)timeStamp,
GetTrackTimeScale(trackId), timeScale);
}
MP4Timestamp MP4File::ConvertToTrackTimestamp(
MP4TrackId trackId,
u_int64_t timeStamp,
u_int32_t timeScale)
{
return (MP4Timestamp)MP4ConvertTime(timeStamp,
timeScale, GetTrackTimeScale(trackId));
}
u_int64_t MP4File::ConvertFromTrackDuration(
MP4TrackId trackId,
MP4Duration duration,
u_int32_t timeScale)
{
return MP4ConvertTime((u_int64_t)duration,
GetTrackTimeScale(trackId), timeScale);
}
MP4Duration MP4File::ConvertToTrackDuration(
MP4TrackId trackId,
u_int64_t duration,
u_int32_t timeScale)
{
return (MP4Duration)MP4ConvertTime(duration,
timeScale, GetTrackTimeScale(trackId));
}
u_int8_t MP4File::ConvertTrackTypeToStreamType(const char* trackType)
{
u_int8_t streamType;
if (!strcmp(trackType, MP4_OD_TRACK_TYPE)) {
streamType = MP4ObjectDescriptionStreamType;
} else if (!strcmp(trackType, MP4_SCENE_TRACK_TYPE)) {
streamType = MP4SceneDescriptionStreamType;
} else if (!strcmp(trackType, MP4_CLOCK_TRACK_TYPE)) {
streamType = MP4ClockReferenceStreamType;
} else if (!strcmp(trackType, MP4_MPEG7_TRACK_TYPE)) {
streamType = MP4Mpeg7StreamType;
} else if (!strcmp(trackType, MP4_OCI_TRACK_TYPE)) {
streamType = MP4OCIStreamType;
} else if (!strcmp(trackType, MP4_IPMP_TRACK_TYPE)) {
streamType = MP4IPMPStreamType;
} else if (!strcmp(trackType, MP4_MPEGJ_TRACK_TYPE)) {
streamType = MP4MPEGJStreamType;
} else {
streamType = MP4UserPrivateStreamType;
}
return streamType;
}
// edit list
char* MP4File::MakeTrackEditName(
MP4TrackId trackId,
MP4EditId editId,
const char* name)
{
char* trakName = MakeTrackName(trackId, NULL);
static char editName[1024];
snprintf(editName, sizeof(editName),
"%s.edts.elst.entries[%u].%s",
trakName, editId - 1, name);
return editName;
}
MP4EditId MP4File::AddTrackEdit(
MP4TrackId trackId,
MP4EditId editId)
{
ProtectWriteOperation("AddTrackEdit");
return m_pTracks[FindTrackIndex(trackId)]->AddEdit(editId);
}
void MP4File::DeleteTrackEdit(
MP4TrackId trackId,
MP4EditId editId)
{
ProtectWriteOperation("DeleteTrackEdit");
m_pTracks[FindTrackIndex(trackId)]->DeleteEdit(editId);
}
u_int32_t MP4File::GetTrackNumberOfEdits(
MP4TrackId trackId)
{
return GetTrackIntegerProperty(trackId, "edts.elst.entryCount");
}
MP4Duration MP4File::GetTrackEditTotalDuration(
MP4TrackId trackId,
MP4EditId editId)
{
return m_pTracks[FindTrackIndex(trackId)]->GetEditTotalDuration(editId);
}
MP4Timestamp MP4File::GetTrackEditStart(
MP4TrackId trackId,
MP4EditId editId)
{
return m_pTracks[FindTrackIndex(trackId)]->GetEditStart(editId);
}
MP4Timestamp MP4File::GetTrackEditMediaStart(
MP4TrackId trackId,
MP4EditId editId)
{
return GetIntegerProperty(
MakeTrackEditName(trackId, editId, "mediaTime"));
}
void MP4File::SetTrackEditMediaStart(
MP4TrackId trackId,
MP4EditId editId,
MP4Timestamp startTime)
{
SetIntegerProperty(
MakeTrackEditName(trackId, editId, "mediaTime"),
startTime);
}
MP4Duration MP4File::GetTrackEditDuration(
MP4TrackId trackId,
MP4EditId editId)
{
return GetIntegerProperty(
MakeTrackEditName(trackId, editId, "segmentDuration"));
}
void MP4File::SetTrackEditDuration(
MP4TrackId trackId,
MP4EditId editId,
MP4Duration duration)
{
SetIntegerProperty(
MakeTrackEditName(trackId, editId, "segmentDuration"),
duration);
}
bool MP4File::GetTrackEditDwell(
MP4TrackId trackId,
MP4EditId editId)
{
return (GetIntegerProperty(
MakeTrackEditName(trackId, editId, "mediaRate")) == 0);
}
void MP4File::SetTrackEditDwell(
MP4TrackId trackId,
MP4EditId editId,
bool dwell)
{
SetIntegerProperty(
MakeTrackEditName(trackId, editId, "mediaRate"),
(dwell ? 0 : 1));
}
MP4SampleId MP4File::GetSampleIdFromEditTime(
MP4TrackId trackId,
MP4Timestamp when,
MP4Timestamp* pStartTime,
MP4Duration* pDuration)
{
return m_pTracks[FindTrackIndex(trackId)]->GetSampleIdFromEditTime(
when, pStartTime, pDuration);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -