📄 mp4creator.cpp
字号:
if (doCreate) {
MP4TrackId* pCreatedTrackIds =
CreateMediaTracks(mp4File, inputFileName);
if (pCreatedTrackIds) {
// decide if we can raise the ISMA compliance tag in SDP
// we do this if audio and/or video are MPEG-4
MP4TrackId* pTrackId = pCreatedTrackIds;
while (*pTrackId != MP4_INVALID_TRACK_ID) {
const char *type =
MP4GetTrackType(mp4File, *pTrackId);
if (!strcmp(type, MP4_AUDIO_TRACK_TYPE)) {
allMpeg4Streams &=
(MP4GetTrackAudioType(mp4File, *pTrackId)
== MP4_MPEG4_AUDIO_TYPE);
} else if (!strcmp(type, MP4_VIDEO_TRACK_TYPE)) {
allMpeg4Streams &=
(MP4GetTrackVideoType(mp4File, *pTrackId)
== MP4_MPEG4_VIDEO_TYPE);
}
pTrackId++;
}
}
if (pCreatedTrackIds && doHint) {
MP4TrackId* pTrackId = pCreatedTrackIds;
while (*pTrackId != MP4_INVALID_TRACK_ID) {
CreateHintTrack(mp4File, *pTrackId,
payloadName, doInterleave, maxPayloadSize);
pTrackId++;
}
}
} else {
CreateHintTrack(mp4File, hintTrackId,
payloadName, doInterleave, maxPayloadSize);
}
MP4Close(mp4File);
if (doCreate) {
// this creates simple MPEG-4 OD and BIFS streams
MP4MakeIsmaCompliant(mp4FileName, Verbosity, allMpeg4Streams);
}
} else if (doExtract) {
if (!mp4FileExists) {
fprintf(stderr,
"%s: can't extract track in file that doesn't exist\n",
ProgName);
exit(EXIT_CREATE_FILE);
}
mp4File = MP4Read(mp4FileName, Verbosity);
if (!mp4File) {
// mp4 library should have printed a message
exit(EXIT_CREATE_FILE);
}
char tempName[PATH_MAX];
if (outputFileName == NULL) {
snprintf(tempName, sizeof(tempName),
"%s.t%u", mp4FileName, extractTrackId);
outputFileName = tempName;
}
ExtractTrack(mp4File, extractTrackId, outputFileName);
MP4Close(mp4File);
} else if (doDelete) {
if (!mp4FileExists) {
fprintf(stderr,
"%s: can't delete track in file that doesn't exist\n",
ProgName);
exit(EXIT_CREATE_FILE);
}
mp4File = MP4Modify(mp4FileName, Verbosity);
if (!mp4File) {
// mp4 library should have printed a message
exit(EXIT_CREATE_FILE);
}
MP4DeleteTrack(mp4File, deleteTrackId);
MP4Close(mp4File);
doOptimize = true; // to purge unreferenced track data
}
if (doOptimize) {
if (!MP4Optimize(mp4FileName, NULL, Verbosity)) {
// mp4 library should have printed a message
exit(EXIT_OPTIMIZE_FILE);
}
}
return(EXIT_SUCCESS);
}
MP4TrackId* CreateMediaTracks(MP4FileHandle mp4File, const char* inputFileName)
{
FILE* inFile = fopen(inputFileName, "rb");
if (inFile == NULL) {
fprintf(stderr,
"%s: can't open file %s: %s\n",
ProgName, inputFileName, strerror(errno));
exit(EXIT_CREATE_MEDIA);
}
struct stat s;
if (fstat(fileno(inFile), &s) < 0) {
fprintf(stderr,
"%s: can't stat file %s: %s\n",
ProgName, inputFileName, strerror(errno));
exit(EXIT_CREATE_MEDIA);
}
if (s.st_size == 0) {
fprintf(stderr,
"%s: file %s is empty\n",
ProgName, inputFileName);
exit(EXIT_CREATE_MEDIA);
}
const char* extension = strrchr(inputFileName, '.');
if (extension == NULL) {
fprintf(stderr,
"%s: no file type extension\n", ProgName);
exit(EXIT_CREATE_MEDIA);
}
static MP4TrackId trackIds[2] = {
MP4_INVALID_TRACK_ID, MP4_INVALID_TRACK_ID
};
MP4TrackId* pTrackIds = trackIds;
if (!strcasecmp(extension, ".avi")) {
fclose(inFile);
inFile = NULL;
pTrackIds = AviCreator(mp4File, inputFileName);
} else if (!strcasecmp(extension, ".aac")) {
trackIds[0] = AacCreator(mp4File, inFile);
} else if (!strcasecmp(extension, ".mp3")
|| !strcasecmp(extension, ".mp1")
|| !strcasecmp(extension, ".mp2")) {
trackIds[0] = Mp3Creator(mp4File, inFile);
} else if (!strcasecmp(extension, ".divx")
|| !strcasecmp(extension, ".mp4v")
|| !strcasecmp(extension, ".m4v")
|| !strcasecmp(extension, ".xvid")
|| !strcasecmp(extension, ".cmp")) {
trackIds[0] = Mp4vCreator(mp4File, inFile);
} else {
fprintf(stderr,
"%s: unknown file type\n", ProgName);
exit(EXIT_CREATE_MEDIA);
}
if (inFile) {
fclose(inFile);
}
return pTrackIds;
}
void CreateHintTrack(MP4FileHandle mp4File, MP4TrackId mediaTrackId,
const char* payloadName, bool interleave, u_int16_t maxPayloadSize)
{
bool rc;
if (MP4GetTrackNumberOfSamples(mp4File, mediaTrackId) == 0) {
fprintf(stderr,
"%s: couldn't create hint track, no media samples\n", ProgName);
exit(EXIT_CREATE_HINT);
}
// vector out to specific hinters
const char* trackType = MP4GetTrackType(mp4File, mediaTrackId);
if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) {
u_int8_t audioType = MP4GetTrackAudioType(mp4File, mediaTrackId);
switch (audioType) {
case MP4_MPEG4_AUDIO_TYPE:
case MP4_MPEG2_AAC_MAIN_AUDIO_TYPE:
case MP4_MPEG2_AAC_LC_AUDIO_TYPE:
case MP4_MPEG2_AAC_SSR_AUDIO_TYPE:
rc = MP4AV_RfcIsmaHinter(mp4File, mediaTrackId,
interleave, maxPayloadSize);
break;
case MP4_MPEG1_AUDIO_TYPE:
case MP4_MPEG2_AUDIO_TYPE:
if (payloadName &&
(!strcasecmp(payloadName, "3119")
|| !strcasecmp(payloadName, "mpa-robust"))) {
rc = MP4AV_Rfc3119Hinter(mp4File, mediaTrackId,
interleave, maxPayloadSize);
} else {
rc = MP4AV_Rfc2250Hinter(mp4File, mediaTrackId,
false, maxPayloadSize);
}
break;
default:
fprintf(stderr,
"%s: can't hint non-MPEG4/non-MP3 audio type\n", ProgName);
exit(EXIT_CREATE_HINT);
}
} else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) {
u_int8_t videoType = MP4GetTrackVideoType(mp4File, mediaTrackId);
if (videoType == MP4_MPEG4_VIDEO_TYPE) {
rc = MP4AV_Rfc3016Hinter(mp4File, mediaTrackId, maxPayloadSize);
} else {
fprintf(stderr,
"%s: can't hint non-MPEG4 video type\n", ProgName);
exit(EXIT_CREATE_HINT);
}
} else {
fprintf(stderr,
"%s: can't hint track type %s\n", ProgName, trackType);
exit(EXIT_CREATE_HINT);
}
if (!rc) {
fprintf(stderr,
"%s: error hinting track %u\n", ProgName, mediaTrackId);
exit(EXIT_CREATE_HINT);
}
}
void ExtractTrack(
MP4FileHandle mp4File,
MP4TrackId trackId,
const char* outputFileName)
{
int outFd = open(outputFileName,
O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (outFd == -1) {
fprintf(stderr, "%s: can't open %s: %s\n",
ProgName, outputFileName, strerror(errno));
exit(EXIT_EXTRACT_TRACK);
}
// some track types have special needs
// to properly recreate their raw ES file
bool prependES = false;
bool prependADTS = false;
const char* trackType =
MP4GetTrackType(mp4File, trackId);
if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) {
if (MP4_IS_MPEG4_VIDEO_TYPE(MP4GetTrackVideoType(mp4File, trackId))) {
prependES = true;
}
} else if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) {
if (MP4_IS_AAC_AUDIO_TYPE(MP4GetTrackAudioType(mp4File, trackId))) {
prependADTS = true;
}
}
MP4SampleId numSamples =
MP4GetTrackNumberOfSamples(mp4File, trackId);
u_int8_t* pSample;
u_int32_t sampleSize;
// extraction loop
for (MP4SampleId sampleId = 1 ; sampleId <= numSamples; sampleId++) {
int rc;
// signal to ReadSample()
// that it should malloc a buffer for us
pSample = NULL;
sampleSize = 0;
if (prependADTS) {
// need some very specialized work for these
MP4AV_AdtsMakeFrameFromMp4Sample(
mp4File,
trackId,
sampleId,
&pSample,
&sampleSize);
} else {
// read the sample
rc = MP4ReadSample(
mp4File,
trackId,
sampleId,
&pSample,
&sampleSize);
if (rc == 0) {
fprintf(stderr, "%s: read sample %u for %s failed\n",
ProgName, sampleId, outputFileName);
exit(EXIT_EXTRACT_TRACK);
}
if (prependES && sampleId == 1) {
u_int8_t* pConfig = NULL;
u_int32_t configSize = 0;
MP4GetTrackESConfiguration(mp4File, trackId,
&pConfig, &configSize);
write(outFd, pConfig, configSize);
free(pConfig);
}
}
rc = write(outFd, pSample, sampleSize);
if (rc == -1 || (u_int32_t)rc != sampleSize) {
fprintf(stderr, "%s: write to %s failed: %s\n",
ProgName, outputFileName, strerror(errno));
exit(EXIT_EXTRACT_TRACK);
}
free(pSample);
}
// close ES file
close(outFd);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -