📄 mp4extract.cpp
字号:
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is MPEG4IP.
*
* The Initial Developer of the Original Code is Cisco Systems Inc.
* Portions created by Cisco Systems Inc. are
* Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved.
*
* Contributor(s):
* Dave Mackie dmackie@cisco.com
*/
// N.B. mp4extract just extracts tracks/samples from an mp4 file
// For many track types this is insufficient to reconsruct a valid
// elementary stream (ES). Use "mp4creator -extract=<trackId>" if
// you need the ES reconstructed.
#include "mp4.h"
#include "mpeg4ip_getopt.h"
char* ProgName;
char* Mp4PathName;
char* Mp4FileName;
// forward declaration
void ExtractTrack(MP4FileHandle mp4File, MP4TrackId trackId,
bool sampleMode, MP4SampleId sampleId, char* dstFileName = NULL);
int main(int argc, char** argv)
{
char* usageString =
"usage: %s [-l] [-t <track-id>] [-s <sample-id>] [-v [<level>]] <file-name>\n";
bool doList = false;
bool doSamples = false;
MP4TrackId trackId = MP4_INVALID_TRACK_ID;
MP4SampleId sampleId = MP4_INVALID_SAMPLE_ID;
char* dstFileName = NULL;
u_int32_t verbosity = MP4_DETAILS_ERROR;
/* begin processing command line */
ProgName = argv[0];
while (true) {
int c = -1;
int option_index = 0;
static struct option long_options[] = {
{ "list", 0, 0, 'l' },
{ "track", 1, 0, 't' },
{ "sample", 2, 0, 's' },
{ "verbose", 2, 0, 'v' },
{ "version", 0, 0, 'V' },
{ NULL, 0, 0, 0 }
};
c = getopt_long_only(argc, argv, "lt:s::v::V",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'l':
doList = true;
break;
case 's':
doSamples = true;
if (optarg) {
if (sscanf(optarg, "%u", &sampleId) != 1) {
fprintf(stderr,
"%s: bad sample-id specified: %s\n",
ProgName, optarg);
}
}
break;
case 't':
if (sscanf(optarg, "%u", &trackId) != 1) {
fprintf(stderr,
"%s: bad track-id specified: %s\n",
ProgName, optarg);
exit(1);
}
break;
case 'v':
verbosity |= MP4_DETAILS_READ;
if (optarg) {
u_int32_t level;
if (sscanf(optarg, "%u", &level) == 1) {
if (level >= 2) {
verbosity |= MP4_DETAILS_TABLE;
}
if (level >= 3) {
verbosity |= MP4_DETAILS_SAMPLE;
}
if (level >= 4) {
verbosity = MP4_DETAILS_ALL;
}
}
}
break;
case '?':
fprintf(stderr, usageString, ProgName);
exit(0);
case 'V':
fprintf(stderr, "%s - %s version %s\n",
ProgName, PACKAGE, VERSION);
exit(0);
default:
fprintf(stderr, "%s: unknown option specified, ignoring: %c\n",
ProgName, c);
}
}
/* check that we have at least one non-option argument */
if ((argc - optind) < 1) {
fprintf(stderr, usageString, ProgName);
exit(1);
}
if (verbosity) {
fprintf(stderr, "%s version %s\n", ProgName, VERSION);
}
/* point to the specified file names */
Mp4PathName = argv[optind++];
/* get dest file name for a single track */
if (trackId && (argc - optind) > 0) {
dstFileName = argv[optind++];
}
char* lastSlash = strrchr(Mp4PathName, '/');
if (lastSlash) {
Mp4FileName = lastSlash + 1;
} else {
Mp4FileName = Mp4PathName;
}
/* warn about extraneous non-option arguments */
if (optind < argc) {
fprintf(stderr, "%s: unknown options specified, ignoring: ", ProgName);
while (optind < argc) {
fprintf(stderr, "%s ", argv[optind++]);
}
fprintf(stderr, "\n");
}
/* end processing of command line */
MP4FileHandle mp4File = MP4Read(Mp4PathName, verbosity);
if (!mp4File) {
exit(1);
}
if (doList) {
MP4Info(mp4File);
exit(0);
}
if (trackId == 0) {
u_int32_t numTracks = MP4GetNumberOfTracks(mp4File);
for (u_int32_t i = 0; i < numTracks; i++) {
trackId = MP4FindTrackId(mp4File, i);
ExtractTrack(mp4File, trackId, doSamples, sampleId);
}
} else {
ExtractTrack(mp4File, trackId, doSamples, sampleId, dstFileName);
}
MP4Close(mp4File);
return(0);
}
void ExtractTrack(MP4FileHandle mp4File, MP4TrackId trackId,
bool sampleMode, MP4SampleId sampleId, char* dstFileName)
{
char outFileName[PATH_MAX];
int outFd = -1;
if (!sampleMode) {
if (dstFileName == NULL) {
snprintf(outFileName, sizeof(outFileName),
"%s.t%u", Mp4FileName, trackId);
} else {
snprintf(outFileName, sizeof(outFileName),
"%s", dstFileName);
}
outFd = open(outFileName,
O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (outFd == -1) {
fprintf(stderr, "%s: can't open %s: %s\n",
ProgName, outFileName, strerror(errno));
return;
}
}
MP4SampleId numSamples;
if (sampleMode && sampleId != MP4_INVALID_SAMPLE_ID) {
numSamples = sampleId;
} else {
sampleId = 1;
numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId);
}
u_int8_t* pSample;
u_int32_t sampleSize;
for ( ; sampleId <= numSamples; sampleId++) {
int rc;
// signals to ReadSample() that it should malloc a buffer for us
pSample = NULL;
sampleSize = 0;
rc = MP4ReadSample(mp4File, trackId, sampleId, &pSample, &sampleSize);
if (rc == 0) {
fprintf(stderr, "%s: read sample %u for %s failed\n",
ProgName, sampleId, outFileName);
break;
}
if (sampleMode) {
snprintf(outFileName, sizeof(outFileName), "%s.t%u.s%u",
Mp4FileName, trackId, sampleId);
outFd = open(outFileName,
O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (outFd == -1) {
fprintf(stderr, "%s: can't open %s: %s\n",
ProgName, outFileName, strerror(errno));
break;
}
}
rc = write(outFd, pSample, sampleSize);
if (rc == -1 || (u_int32_t)rc != sampleSize) {
fprintf(stderr, "%s: write to %s failed: %s\n",
ProgName, outFileName, strerror(errno));
break;
}
free(pSample);
if (sampleMode) {
close(outFd);
outFd = -1;
}
}
if (outFd != -1) {
close(outFd);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -