📄 mp4creator.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-2004. All Rights Reserved. * * Portions created by Ximpo Group Ltd. are * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. * * Contributor(s): * Dave Mackie dmackie@cisco.com * Alix Marchandise-Franquet alix@cisco.com * Ximpo Group Ltd. mp4v2@ximpo.com */#define MP4CREATOR_GLOBALS#include "mp4creator.h"#include "mpeg4ip_getopt.h"#include "mpeg.h"// forward declarations// AMR defines#define AMR_TYPE_NONE 0#define AMR_TYPE_AMR 1#define AMR_TYPE_AMRWB 2#define AMR_MAGIC_LEN_AMR 6#define AMR_MAGIC_AMR "#!AMR\n"#define AMR_MAGIC_LEN_AMRWB 9#define AMR_MAGIC_AMRWB "#!AMR-WB\n"MP4TrackId* CreateMediaTracks( MP4FileHandle mp4File, const char* inputFileName, bool doEncrypt);void CreateHintTrack( MP4FileHandle mp4File, MP4TrackId mediaTrackId, const char* payloadName, bool interleave, u_int16_t maxPayloadSize, bool doEncrypt);void ExtractTrack( MP4FileHandle mp4File, MP4TrackId trackId, const char* outputFileName);static bool Is3GPP(MP4FileHandle mp4File);// external declarations// track creatorsMP4TrackId* AviCreator(MP4FileHandle mp4File, const char* aviFileName, bool doEncrypt);MP4TrackId AacCreator(MP4FileHandle mp4File, FILE* inFile, bool doEncrypt);MP4TrackId Mp3Creator(MP4FileHandle mp4File, FILE* inFile, bool doEncrypt);MP4TrackId Mp4vCreator(MP4FileHandle mp4File, FILE* inFile, bool doEncrypt, bool doVariableRate);MP4TrackId AmrCreator(MP4FileHandle mp4File, FILE* inFile, bool doEncrypt);MP4TrackId H263Creator(MP4FileHandle mp4File, FILE* inFile, u_int8_t h263Profile, u_int8_t h263Level, bool setBitrates, u_int8_t cbrTolerance);MP4TrackId H264Creator(MP4FileHandle mp4File, FILE *inFile);u_int8_t h263Profile = 0;u_int8_t h263Level = 10;u_int8_t H263CbrTolerance = 0;bool setBitrates = false;static bool allowVariableFrameRate = false;static bool allowAvi = false;// main routineint main(int argc, char** argv){ char* usageString = " <options> <mp4-file>\n" " Options:\n" " -aac-old-file-format Use old file format with 58 bit adts headers\n" " -aac-profile=[2|4] Force AAC to mpeg2 or mpeg4 profile\n" " -allow-avi-files Allow avi files\n" " -calcH263Bitrates Calculate and add bitrate information\n" " -create=<input-file> Create track from <input-file>\n" " input files can be of type: .263 .aac .amr .mp3 .divx .mp4v .m4v .cmp .xvid\n" " -encrypt[=<track-id>] Encrypt a track, also -E\n" " -extract=<track-id> Extract a track\n" " -delete=<track-id> Delete a track\n" " -force3GPCompliance Force making the file 3GP compliant. This disables ISMA compliance.\n" " -forceH263Profile=<profile> Force using H.263 Profile <profile> (default is 0)\n" " -forceH263Level=<level> Force using H.263 level <level> (default is 10)\n" " -H263CbrTolerance=<value> Define H.263 CBR tolerance of [value] (default: 10%)\n" " -hint[=<track-id>] Create hint track, also -H\n" " -interleave Use interleaved audio payload format, also -I\n" " -list List tracks in mp4 file\n" " -make-isma-10-compliant Insert bifs and od tracks required for some ISMA players (also -i)\n" " -mpeg4-video-profile=<level> Mpeg4 video profile override\n" " -mtu=<size> Maximum Payload size for RTP packets in hint track\n" " -optimize Optimize mp4 file layout\n" " -payload=<payload> Rtp payload type \n" " (use 3119 or mpa-robust for mp3 rfc 3119 support)\n" " -rate=<fps> Video frame rate, e.g. 30 or 29.97\n" " -timescale=<ticks> Time scale (ticks per second)\n" " -use64bits Use for large files\n" " -use64bitstime Use for 64 Bit times (not QT player compatible)\n" " -variable-frame-rate Enable variable frame rate for mpeg4 video\n" " -verbose[=[1-5]] Enable debug messages\n" " -version Display version information\n" ; bool doCreate = false; bool doEncrypt = false; bool doExtract = false; bool doDelete = false; bool doHint = false; bool doList = false; bool doOptimize = false; bool doInterleave = false; bool doIsma = false; uint64_t createFlags = 0; char* mp4FileName = NULL; char* inputFileName = NULL; char* outputFileName = NULL; char* payloadName = NULL; MP4TrackId hintTrackId = MP4_INVALID_TRACK_ID; MP4TrackId encryptTrackId = MP4_INVALID_TRACK_ID; MP4TrackId extractTrackId = MP4_INVALID_TRACK_ID; MP4TrackId deleteTrackId = MP4_INVALID_TRACK_ID; u_int16_t maxPayloadSize = 1460; bool force3GPCompliance = false; char* p3gppSupportedBrands[2] = {"3gp5", "3gp4"}; uint32_t newverbosity; Verbosity = MP4_DETAILS_ERROR; VideoFrameRate = 0; // determine from input file TimeScaleSpecified = false; Mp4TimeScale = 90000; VideoProfileLevelSpecified = false; aacUseOldFile = false; aacProfileLevel = 0; // begin processing command line ProgName = argv[0]; while (true) { int c = -1; int option_index = 0; static struct option long_options[] = { { "aac-old-file-format", 0, 0, 'a' }, { "aac-profile", 1, 0, 'A'}, { "allow-avi-files", 0, 0, 'B'}, { "calcH263Bitrates", 0, 0, 'C'}, { "create", 1, 0, 'c' }, { "delete", 1, 0, 'd' }, { "extract", 2, 0, 'e' }, { "encrypt", 2, 0, 'E' }, { "force3GPCompliance", 0, 0, 'G'}, { "forceH263Profile", 1, 0, 'P'}, { "forceH263Level", 1, 0, 'L'}, { "H263CbrTolerance", 1, 0, 'T' }, { "help", 0, 0, '?' }, { "hint", 2, 0, 'H' }, { "interleave", 0, 0, 'I' }, { "list", 0, 0, 'l' }, { "make-isma-10-compliant", 0, 0, 'i' }, { "mpeg4-video-profile", 1, 0, 'M' }, { "mtu", 1, 0, 'm' }, { "optimize", 0, 0, 'O' }, { "payload", 1, 0, 'p' }, { "rate", 1, 0, 'r' }, { "timescale", 1, 0, 't' }, { "use64bits", 0, 0, 'u' }, { "use64bitstime", 0, 0, 'U' }, { "variable-frame-rate", 0, 0, 'Z'}, { "verbose", 2, 0, 'v' }, { "version", 0, 0, 'V' }, { NULL, 0, 0, 0 } }; c = getopt_long_only(argc, argv, "aBc:Cd:e:E::GH::iIlL:m:Op:P:r:t:T:uUv::VZ", long_options, &option_index); if (c == -1) break; switch (c) { case 'a': aacUseOldFile = true; break; case 'A': if (sscanf(optarg, "%u", &aacProfileLevel) != 1 || (aacProfileLevel != 2 && aacProfileLevel != 4)) { fprintf(stderr, "%s: bad mpeg version specified %d\n", ProgName, aacProfileLevel); exit(EXIT_COMMAND_LINE); } fprintf(stderr, "Warning - you have changed the AAC profile level. This is not recommended\nIf you have problems with the resultant file, it is your own fault\nDo not contact project creators\n"); break; case 'B': allowAvi = true; break; case 'c': doCreate = true; inputFileName = optarg; break; case 'C': setBitrates = true; break; case 'd': if (optarg == NULL) { fprintf(stderr, "%s:no track-id specified for delete\n", ProgName); exit(EXIT_COMMAND_LINE); } if (sscanf(optarg, "%u", &deleteTrackId) != 1) { fprintf(stderr, "%s: bad track-id specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } doDelete = true; break; case 'e': if (optarg == NULL) { fprintf(stderr, "%s:no track-id specified for extract\n", ProgName); exit(EXIT_COMMAND_LINE); } if (sscanf(optarg, "%u", &extractTrackId) != 1) { fprintf(stderr, "%s: bad track-id specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } doExtract = true; break; case 'E': doEncrypt = true; if (optarg) { // if the short version of option is given, optarg has // an = at the beginning. this causes sscanf to fail. // if the long version of the option is given, there // is no = if ( optarg[0] == '=' ) optarg[0] = ' '; if (sscanf(optarg, "%d", &encryptTrackId) != 1) { fprintf(stderr, "%s: bad track-id specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } } break; case 'G': force3GPCompliance = true; break; case 'H': doHint = true; if (optarg) { // if the short version of option is given, optarg has // an = at the beginning. this causes sscanf to fail. // if the long version of the option is given, there // is no = if ( optarg[0] == '=' ) optarg[0] = ' '; if (sscanf(optarg, "%u", &hintTrackId) != 1) { fprintf(stderr, "%s: bad track-id specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } } break; case 'i': doIsma = true; break; case 'I': doInterleave = true; break; case 'l': doList = true; break; case 'L': if (!optarg || (sscanf(optarg, "%hhu", &h263Level) != 1)) { fprintf(stderr, "%s: bad h263Level specified: %s\n", ProgName, optarg ? optarg : "<none>"); exit(EXIT_COMMAND_LINE); } break; case 'm': u_int32_t mtu; if (optarg == NULL) { fprintf(stderr, "%s:no mtu specified\n", ProgName); exit(EXIT_COMMAND_LINE); } if (sscanf(optarg, "%u", &mtu) != 1 || mtu < 64) { fprintf(stderr, "%s: bad mtu specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } maxPayloadSize = mtu - 40; // subtract IP, UDP, and RTP hdrs break; case 'M': if (optarg == NULL) { fprintf(stderr, "%s:no video profile specifed\n", ProgName); exit(EXIT_COMMAND_LINE); } if (sscanf(optarg, "%i", &VideoProfileLevel) != 1 || (VideoProfileLevel < 0 || VideoProfileLevel > MPEG4_FGSP_L5)) { fprintf(stderr, "%s: bad mpeg4 video profile level specified %d\n", ProgName, VideoProfileLevel); exit(EXIT_COMMAND_LINE); } VideoProfileLevelSpecified = TRUE; break; case 'O': doOptimize = true; break; case 'p': payloadName = optarg; break; case 'P': if (!optarg || (sscanf(optarg, "%hhu", &h263Profile) != 1)) { fprintf(stderr, "%s: bad h263Profile specifed: %s\n", ProgName, optarg ? optarg : "<none>"); exit(EXIT_COMMAND_LINE); } break; case 'r': if (optarg == NULL) { fprintf(stderr, "%s:no rate specifed\n", ProgName); exit(EXIT_COMMAND_LINE); } if (sscanf(optarg, "%lf", &VideoFrameRate) != 1) { fprintf(stderr, "%s: bad rate specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } break; case 't': if (optarg == NULL) { fprintf(stderr, "%s:no time scale specifed\n", ProgName); exit(EXIT_COMMAND_LINE); } if (sscanf(optarg, "%u", &Mp4TimeScale) != 1) { fprintf(stderr, "%s: bad timescale specified: %s\n", ProgName, optarg); exit(EXIT_COMMAND_LINE); } TimeScaleSpecified = true; break; case 'T': if (!optarg || (sscanf(optarg, "%hhu", &H263CbrTolerance) != 1)) { fprintf(stderr, "%s: bad H263CbrTolerance specified: %s\n", ProgName, optarg ? optarg : "<none>"); exit(EXIT_COMMAND_LINE); } break; case 'u': createFlags |= MP4_CREATE_64BIT_DATA; break; case 'U': createFlags |= MP4_CREATE_64BIT_TIME; break; case 'v': Verbosity |= (MP4_DETAILS_READ | MP4_DETAILS_WRITE); 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_HINT; } if (level >= 5) { Verbosity = MP4_DETAILS_ALL; } } } break; case '?': fprintf(stderr, "usage: %s %s", ProgName, usageString); exit(EXIT_SUCCESS); case 'V': fprintf(stderr, "%s - %s version %s\n", ProgName, MPEG4IP_PACKAGE, MPEG4IP_VERSION); exit(EXIT_SUCCESS); case 'Z': allowVariableFrameRate = true; break; 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, "usage: %s %s", ProgName, usageString); exit(EXIT_COMMAND_LINE); } if ((argc - optind) == 1) { mp4FileName = argv[optind++]; } else { // it appears we have two file names if (doExtract) { mp4FileName = argv[optind++]; outputFileName = argv[optind++]; } else { if (inputFileName == NULL) { // then assume -c for the first file name doCreate = true; inputFileName = argv[optind++]; } mp4FileName = argv[optind++]; } } // 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"); } // operations consistency checks if (!doList && !doCreate && !doHint && !doEncrypt && !doOptimize && !doExtract && !doDelete && !doIsma) { fprintf(stderr, "%s: no operation specified\n", ProgName); exit(EXIT_COMMAND_LINE); } if ((doCreate || doHint || doEncrypt || doIsma) && doExtract) { fprintf(stderr, "%s: extract operation must be done separately\n", ProgName); exit(EXIT_COMMAND_LINE); } if ((doCreate || doHint || doEncrypt || doIsma) && doDelete) { fprintf(stderr, "%s: delete operation must be done separately\n", ProgName); exit(EXIT_COMMAND_LINE); } if (doExtract && doDelete) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -