⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4creator.cpp

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 CPP
📖 第 1 页 / 共 2 页
字号:

		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 + -