📄 mp4creator.cpp
字号:
return pTrackIds;}void CreateHintTrack(MP4FileHandle mp4File, MP4TrackId mediaTrackId, const char* payloadName, bool interleave, u_int16_t maxPayloadSize, bool doEncrypt){ bool rc = FALSE; if (MP4GetTrackNumberOfSamples(mp4File, mediaTrackId) == 0) { fprintf(stderr, "%s: couldn't create hint track, no media samples\n", ProgName); MP4Close(mp4File); exit(EXIT_CREATE_HINT); } // vector out to specific hinters const char* trackType = MP4GetTrackType(mp4File, mediaTrackId); if (doEncrypt || MP4IsIsmaCrypMediaTrack(mp4File, mediaTrackId)) { ismacryp_session_id_t icSID; mp4av_ismacrypParams *icPp = (mp4av_ismacrypParams *) malloc(sizeof(mp4av_ismacrypParams)); memset(icPp, 0, sizeof(mp4av_ismacrypParams)); if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) { if (ismacrypInitSession(&icSID, KeyTypeAudio) != 0) { fprintf(stderr, "%s: can't hint, error in init ismacryp session\n", ProgName); goto quit_error; } } else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) { if (ismacrypInitSession(&icSID, KeyTypeVideo) != 0) { fprintf(stderr, "%s: can't hint, error in init ismacryp session\n", ProgName); goto quit_error; } } else { fprintf(stderr, "%s: can't hint track type %s\n", ProgName, trackType); goto quit_error; } // get all the ismacryp parameters needed by the hinters: if (ismacrypGetKeyCount(icSID, &(icPp->key_count)) != 0) { fprintf(stderr, "%s: can't hint, error getting key count for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetKeyIndicatorLength(icSID, &(icPp->key_ind_len)) != 0) { fprintf(stderr, "%s: can't hint, error getting key ind len for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetKeyIndPerAU(icSID, &(icPp->key_ind_perau)) != 0) { fprintf(stderr, "%s: can't hint, error getting key ind per au for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetSelectiveEncryption(icSID, &(icPp->selective_enc)) != 0) { fprintf(stderr, "%s: can't hint, error getting selective enc for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetDeltaIVLength(icSID, &(icPp->delta_iv_len)) != 0) { fprintf(stderr, "%s: can't hint, error getting delta iv len for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetIVLength(icSID, &(icPp->iv_len)) != 0) { fprintf(stderr, "%s: can't hint, error getting iv len for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetScheme(icSID, (ismacryp_scheme_t *) &(icPp->scheme)) != 0) { fprintf(stderr, "%s: can't hint, error getting scheme for session %d\n", ProgName, icSID); goto quit_error; } if (ismacrypGetKey(icSID, 1,&(icPp->key_len),&(icPp->salt_len), &(icPp->key),&(icPp->salt),&(icPp->key_life)) != 0) { fprintf(stderr, "%s: can't hint, error getting scheme for session %d\n", ProgName, icSID); goto quit_error; } goto ok_continue; quit_error: ismacrypEndSession(icSID); MP4Close(mp4File); exit(EXIT_CREATE_HINT); ok_continue: if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) { rc = MP4AV_RfcCryptoAudioHinter(mp4File, mediaTrackId, icPp, interleave, maxPayloadSize, "enc-mpeg4-generic"); ismacrypEndSession(icSID); } else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) { rc = MP4AV_RfcCryptoVideoHinter(mp4File, mediaTrackId, icPp, maxPayloadSize, "enc-mpeg4-generic"); ismacrypEndSession(icSID); } else { fprintf(stderr, "%s: can't hint track type %s\n", ProgName, trackType); } } else if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) { const char *media_data_name; media_data_name = MP4GetTrackMediaDataName(mp4File, mediaTrackId); if (strcasecmp(media_data_name, "mp4a") == 0) { u_int8_t audioType = MP4GetTrackEsdsObjectTypeId(mp4File, mediaTrackId); switch (audioType) { case MP4_INVALID_AUDIO_TYPE: case MP4_MPEG4_AUDIO_TYPE: if (payloadName && (strcasecmp(payloadName, "latm") == 0 || strcasecmp(payloadName, "mp4a-latm") == 0)) { rc = MP4AV_Rfc3016LatmHinter(mp4File, mediaTrackId, maxPayloadSize); break; } 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; case MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE: case MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE: rc = L16Hinter(mp4File, mediaTrackId, maxPayloadSize); break; case MP4_ULAW_AUDIO_TYPE: case MP4_ALAW_AUDIO_TYPE: rc = G711Hinter(mp4File, mediaTrackId, maxPayloadSize); break; default: fprintf(stderr, "%s: can't hint non-MPEG4/non-MP3 audio type\n", ProgName); } } else if (strcasecmp(media_data_name, "samr") == 0 || strcasecmp(media_data_name, "sawb") == 0) { rc = MP4AV_Rfc3267Hinter(mp4File, mediaTrackId, maxPayloadSize); } } else if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) { const char *media_data_name; media_data_name = MP4GetTrackMediaDataName(mp4File, mediaTrackId); if (strcasecmp(media_data_name, "mp4v") == 0) { u_int8_t videoType = MP4GetTrackEsdsObjectTypeId(mp4File, mediaTrackId); switch (videoType) { case MP4_MPEG4_VIDEO_TYPE: rc = MP4AV_Rfc3016Hinter(mp4File, mediaTrackId, maxPayloadSize); break; case MP4_MPEG1_VIDEO_TYPE: case MP4_MPEG2_SIMPLE_VIDEO_TYPE: case MP4_MPEG2_MAIN_VIDEO_TYPE: rc = Mpeg12Hinter(mp4File, mediaTrackId, maxPayloadSize); break; default: fprintf(stderr, "%s: can't hint non-MPEG4 video type\n", ProgName); break; } } else if (strcasecmp(media_data_name, "avc1") == 0) { // h264; rc = MP4AV_H264Hinter(mp4File, mediaTrackId, maxPayloadSize); } else if (strcasecmp(media_data_name, "s263") == 0) { rc = MP4AV_Rfc2429Hinter(mp4File, mediaTrackId, maxPayloadSize); } } else { fprintf(stderr, "%s: can't hint track type %s\n", ProgName, trackType); } if (!rc) { fprintf(stderr, "%s: error hinting track %u\n", ProgName, mediaTrackId); MP4Close(mp4File); exit(EXIT_CREATE_HINT); }}static void extract_h264_track (MP4FileHandle mp4File, MP4TrackId trackId, int outFd, const char *outputFileName){ uint8_t **seqheader, **pictheader; uint32_t *pictheadersize, *seqheadersize; uint32_t ix; uint8_t header[4] = {0, 0, 0, 1}; MP4GetTrackH264SeqPictHeaders(mp4File, trackId, &seqheader, &seqheadersize, &pictheader, &pictheadersize); for (ix = 0; seqheadersize[ix] != 0; ix++) { write(outFd, header, 4); write(outFd, seqheader[ix], seqheadersize[ix]); } for (ix = 0; pictheadersize[ix] != 0; ix++) { write(outFd, header, 4); write(outFd, pictheader[ix], pictheadersize[ix]); } MP4SampleId numSamples = MP4GetTrackNumberOfSamples(mp4File, trackId); u_int8_t* pSample; u_int32_t sampleSize; uint32_t buflen_size; MP4GetTrackH264LengthSize(mp4File, trackId, &buflen_size); // extraction loop for (MP4SampleId sampleId = 1 ; sampleId <= numSamples; sampleId++) { pSample = NULL; sampleSize = 0; int 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); } uint32_t read_offset = 0; uint32_t nal_len; bool first = true;#if 0 printf("\n\nsample id: %u\n", sampleId);#endif do {#if 0 printf("read offset %u buflen %u sample Size %u\n", read_offset, buflen_size, sampleSize);#endif if (read_offset + buflen_size >= sampleSize) { fprintf(stderr, "extra bytes at end of sample %d - nal len size %u, %u bytes left", sampleId, buflen_size, sampleSize - read_offset); read_offset = sampleSize; } else { if (buflen_size == 1) { nal_len = pSample[read_offset]; } else { nal_len = (pSample[read_offset] << 8) | pSample[read_offset + 1]; if (buflen_size == 4) { nal_len <<= 16; nal_len |= (pSample[read_offset + 2] << 8) | pSample[read_offset + 3]; } }#if 0 printf("read offset %u nallen %u sample Size %u %d\n", read_offset, nal_len, sampleSize, first);#endif if (read_offset + nal_len > sampleSize) { fprintf(stderr, "nal length past end of buffer - sample %u size %u frame offset %u left %u\n", sampleId, nal_len, read_offset, sampleSize - read_offset); read_offset = sampleSize; } else { if (first) { write(outFd, header, 4); first = false; } else { write(outFd, header + 1, 3); } // printf("sample id %d size %u %x\n", sampleId, nal_len, nal_len); write(outFd, pSample + read_offset + buflen_size, nal_len); read_offset += nal_len + buflen_size; } } } while (read_offset < sampleSize); free(pSample); } close(outFd);}void ExtractTrack (MP4FileHandle mp4File, MP4TrackId trackId, const char* outputFileName){ int openFlags = O_WRONLY | O_TRUNC | OPEN_CREAT; u_int8_t amrType = AMR_TYPE_NONE; int outFd = open(outputFileName, openFlags, 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); const char *media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); if (!strcmp(trackType, MP4_VIDEO_TRACK_TYPE)) { if (strcmp(media_data_name, "avc1") == 0) { extract_h264_track(mp4File, trackId, outFd, outputFileName); return; } prependES = true; } else if (!strcmp(trackType, MP4_AUDIO_TRACK_TYPE)) { if (strcmp(media_data_name, "mp4a") == 0) { uint8_t type = MP4GetTrackEsdsObjectTypeId(mp4File, trackId); if (MP4_IS_AAC_AUDIO_TYPE(type) || type == MP4_MPEG4_INVALID_AUDIO_TYPE) prependADTS = true; } else if (strcmp(media_data_name, "sawb") == 0) { amrType = AMR_TYPE_AMRWB; } else if (strcmp(media_data_name, "samr") == 0) { amrType = AMR_TYPE_AMR; } switch (amrType) { case AMR_TYPE_AMR: if (write(outFd, AMR_MAGIC_AMR, AMR_MAGIC_LEN_AMR) != AMR_MAGIC_LEN_AMR) { fprintf(stderr, "%s: can't write to file: %s\n", ProgName, strerror(errno)); return; } break; case AMR_TYPE_AMRWB: if (write(outFd, AMR_MAGIC_AMRWB, AMR_MAGIC_LEN_AMRWB) != AMR_MAGIC_LEN_AMRWB) { fprintf(stderr, "%s: can't write to file: %s\n", ProgName, strerror(errno)); return; } break; default: break; } } MP4SampleId numSamples = #if 1 MP4GetTrackNumberOfSamples(mp4File, trackId);#else 1;#endif 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, aacProfileLevel, &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; if (MP4GetTrackESConfiguration(mp4File, trackId, &pConfig, &configSize)) { if (configSize != 0) { write(outFd, pConfig, configSize); } CHECK_AND_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);}bool Is3GPP(MP4FileHandle mp4File){ u_int32_t numberOfTracks = MP4GetNumberOfTracks(mp4File); u_int32_t i; for (i = 0 ; i < numberOfTracks ; i++) { MP4TrackId trackId = MP4FindTrackId(mp4File, i); const char *type, *media_data_name; type = MP4GetTrackType(mp4File, trackId); media_data_name = MP4GetTrackMediaDataName(mp4File, trackId); if (strcmp(type, MP4_VIDEO_TRACK_TYPE) == 0) { if (strcmp(media_data_name, "s263") != 0) { return false; } } else if (strcmp(type, MP4_AUDIO_TRACK_TYPE) == 0) { if (strcmp(media_data_name, "samr") != 0 && strcmp(media_data_name, "sawb") != 0) return false; } } return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -