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

📄 avi.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 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. 2000-2002.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com *//*  * Notes: *  - file formatted with tabstops == 4 spaces  */#include <mp4creator.h>#include <avilib.h>static MP4TrackId VideoCreator(MP4FileHandle mp4File, avi_t* aviFile){	char* videoType = AVI_video_compressor(aviFile);	u_int8_t videoProfileLevel = 0x03;	if (strcasecmp(videoType, "divx")	  && strcasecmp(videoType, "dx50")	  && strcasecmp(videoType, "xvid")) {		fprintf(stderr,				"%s: video compressor %s not recognized\n",			 ProgName, videoType);		return MP4_INVALID_TRACK_ID;	}	double frameRate = AVI_video_frame_rate(aviFile);	if (frameRate == 0) {		fprintf(stderr,				"%s: no video frame rate in avi file\n", ProgName);		return MP4_INVALID_TRACK_ID;	}#ifdef _WIN32	MP4Duration mp4FrameDuration;	mp4FrameDuration = 		(MP4Duration)((double)Mp4TimeScale / frameRate);#else	MP4Duration mp4FrameDuration = 		(MP4Duration)(Mp4TimeScale / frameRate);#endif	MP4TrackId trackId = MP4AddVideoTrack(		mp4File,		Mp4TimeScale, 		mp4FrameDuration, 		AVI_video_width(aviFile), 		AVI_video_height(aviFile), 		MP4_MPEG4_VIDEO_TYPE);	if (trackId == MP4_INVALID_TRACK_ID) {		fprintf(stderr,				"%s: can't create video track\n", ProgName);		return MP4_INVALID_TRACK_ID;	}	int32_t i;	int32_t numFrames = AVI_video_frames(aviFile);	int32_t frameSize;	int32_t maxFrameSize = 0;	// determine maximum video frame size	AVI_seek_start(aviFile);	for (i = 0; i < numFrames; i++) {		frameSize = AVI_frame_size(aviFile, i);		if (frameSize > maxFrameSize) {			maxFrameSize = frameSize;		}	}	// allocate a large enough frame buffer	u_int8_t* pFrameBuffer = (u_int8_t*)malloc(maxFrameSize + 4);	if (pFrameBuffer == NULL) {		fprintf(stderr,				"%s: can't allocate memory\n", ProgName);		MP4DeleteTrack(mp4File, trackId);		return MP4_INVALID_TRACK_ID;	}	AVI_seek_start(aviFile);	// read first frame, should contain VO/VOL and I-VOP	frameSize = AVI_read_frame(aviFile, (char*)pFrameBuffer);	if (frameSize < 0) {		fprintf(stderr,				"%s: can't read video frame 1: %s\n",			ProgName, AVI_strerror());		MP4DeleteTrack(mp4File, trackId);		return MP4_INVALID_TRACK_ID;	}	// find VOP start code in first sample	static u_int8_t startCode[3] = { 		0x00, 0x00, 0x01, 	};	u_int32_t vopStart = 0;	bool foundVOP = false;	bool foundVOSH = false;	bool foundVisualObjectStart = false;	bool foundVO = false;	bool foundVOL = false;	// Note that we go from 4 to framesize, not 0 to framesize - 4	// this is adding padding at the beginning for the VOSH, if	// needed	for (i = 0; foundVOP == false && i < frameSize; i++) {	  if (!memcmp(&pFrameBuffer[i], startCode, 3)) {	    // everything before the VOP	    // should be configuration info	    if (pFrameBuffer[i + 3] == MP4AV_MPEG4_VOP_START) {	      vopStart = i;	      foundVOP = true;	    } else if (pFrameBuffer[i + 3] == MP4AV_MPEG4_VOL_START) {	      u_int8_t timeBits = 15;	      u_int16_t timeTicks = 30000;	      u_int16_t frameDuration = 3000;	      u_int16_t frameWidth = 0;	      u_int16_t frameHeight = 0;	      if (MP4AV_Mpeg4ParseVol(pFrameBuffer + i, frameSize - i, 				      &timeBits, &timeTicks, &frameDuration, 				      &frameWidth, &frameHeight) == false) {		fprintf(stderr, "Couldn't parse vol\n");	      }	      if (frameWidth != AVI_video_width(aviFile)) {		fprintf(stderr, 			"%s:avi file video width does not match VOL header - %d vs. %d\n", 			ProgName, frameWidth, AVI_video_width(aviFile));	      }	      if (frameHeight != AVI_video_height(aviFile)) {		fprintf(stderr, 			"%s:avi file video height does not match VOL header - %d vs. %d\n", 			ProgName, frameHeight, AVI_video_height(aviFile));	      }	      foundVOL = true;	      	    } else if (pFrameBuffer[i + 3] == MP4AV_MPEG4_VOSH_START) {	      foundVOSH = true;	      MP4AV_Mpeg4ParseVosh(pFrameBuffer + i, 				   frameSize - i, 				   &videoProfileLevel);	    } else if (pFrameBuffer[i + 3] == MP4AV_MPEG4_VO_START) {	      foundVisualObjectStart = true;	    } else if (pFrameBuffer[i + 3] <= 0x1f) {	      foundVO = true;	    }	    i += 3; // skip past header	  }	}	if (foundVOSH == false) {	  fprintf(stderr, 		  "%s: Warning: no Visual Object Sequence Start (VOSH) header found in MPEG-4 video.\n"		  "This can cause problems with players other than mp4player included\n"		  "with this package.\n", ProgName);	} else {	  if (VideoProfileLevelSpecified &&	      videoProfileLevel != VideoProfileLevel) {	    fprintf(stderr, 		    "%s: You have specified a different video profile level than was detected in the VOSH header\n"		    "The level you specified was %d and %d was read from the VOSH\n",		    ProgName, VideoProfileLevel, videoProfileLevel);	  }	}	if (foundVisualObjectStart == false) {	  fprintf(stderr, 		  "%s: Warning: no Visual Object start header found in MPEG-4 video.\n"		  "This can cause problems with players other than mp4player included\n"		  "with this package.\n", ProgName);	}	  	if (foundVO == false) {	  fprintf(stderr, 		  "%s: Warning: No VO header found in mpeg-4 video.\n"		  "This can cause problems with players other than mp4player\n",		  ProgName);	}	if (foundVOL == false) {	  fprintf(stderr, 		  "%s: fatal: No VOL header found in mpeg-4 video stream\n",		  ProgName);	  MP4DeleteTrack(mp4File, trackId);	  return MP4_INVALID_TRACK_ID;	}#if 0	// the below will write a VOSH and VO if one doesn't exist	if (foundVOSH == false || 	    foundVisualObjectStart == false) {	  uint8_t *tempes = (uint8_t *)malloc(vopStart + 1 + 5 + 9);	  uint32_t templen = 0;	  if (foundVOSH == false) {	    MP4AV_Mpeg4CreateVosh(&tempes,&templen, videoProfileLevel);	  }	  if (foundVisualObjectStart == false) {	    MP4AV_Mpeg4CreateVo(&tempes, &templen, 1);	  }	  memcpy(tempes + templen, 		 pFrameBuffer, 		 vopStart + 1);	  MP4SetTrackESConfiguration(mp4File, trackId, 				     tempes, 				     vopStart + 1 + templen);	  free(tempes);	} else {	  MP4SetTrackESConfiguration(mp4File, trackId,				     pFrameBuffer, vopStart + 1);	}#else	MP4SetTrackESConfiguration(mp4File, trackId,				   pFrameBuffer, vopStart + 1);#endif	if (MP4GetNumberOfTracks(mp4File, MP4_VIDEO_TRACK_TYPE) == 1) {	  if (VideoProfileLevelSpecified) {	    videoProfileLevel = VideoProfileLevel;	  }	  MP4SetVideoProfileLevel(mp4File, 				  MP4AV_Mpeg4VideoToSystemsProfileLevel(videoProfileLevel));	}	// write out the first frame, minus the initial configuration info	MP4WriteSample(		mp4File, 		trackId, 		&pFrameBuffer[vopStart], 		frameSize - vopStart, 		mp4FrameDuration, 		0, 		true);	// process the rest of the frames	for (i = 1; i < numFrames; i++) {		// read the frame from the AVI file		frameSize = AVI_read_frame(aviFile, (char*)pFrameBuffer);		if (frameSize < 0) {			fprintf(stderr,					"%s: can't read video frame %i: %s\n",				ProgName, i + 1, AVI_strerror());			MP4DeleteTrack(mp4File, trackId);			return MP4_INVALID_TRACK_ID;		}		// we mark random access points in MP4 files		bool isIFrame = 			(MP4AV_Mpeg4GetVopType(pFrameBuffer, frameSize) == 'I');		// write the frame to the MP4 file		MP4WriteSample(mp4File, trackId, 			pFrameBuffer, frameSize, mp4FrameDuration, 0, isIFrame);	}	return trackId;}static inline u_int32_t BytesToInt32(u_int8_t* pBytes) {	return (pBytes[0] << 24) | (pBytes[1] << 16) 		| (pBytes[2] << 8) | pBytes[3];}static MP4TrackId AudioCreator(MP4FileHandle mp4File, avi_t* aviFile){	int32_t audioType = AVI_audio_format(aviFile);	// Check for MP3 audio type	if (audioType != 0x55) {		fprintf(stderr,				"%s: audio compressor 0x%x not recognized\n",			 ProgName, audioType);		return MP4_INVALID_TRACK_ID;	}	u_int8_t temp[4];	u_int32_t mp3header;	AVI_seek_start(aviFile);	if (AVI_read_audio(aviFile, (char*)&temp, 4) != 4) {		fprintf(stderr,				"%s: can't read audio frame 0: %s\n",			ProgName, AVI_strerror());		return MP4_INVALID_TRACK_ID;	}	mp3header = BytesToInt32(temp);	// check mp3header sanity	if ((mp3header & 0xFFE00000) != 0xFFE00000) {		fprintf(stderr,				"%s: data in file doesn't appear to be valid mp3 audio\n",			ProgName);		return MP4_INVALID_TRACK_ID;	}	u_int16_t samplesPerSecond = 		MP4AV_Mp3GetHdrSamplingRate(mp3header);	u_int16_t samplesPerFrame = 		MP4AV_Mp3GetHdrSamplingWindow(mp3header);	u_int8_t mp4AudioType = 		MP4AV_Mp3ToMp4AudioType(MP4AV_Mp3GetHdrVersion(mp3header));	if (audioType == MP4_INVALID_AUDIO_TYPE	  || samplesPerSecond == 0) {		fprintf(stderr,				"%s: data in file doesn't appear to be valid mp3 audio\n",			 ProgName);		return MP4_INVALID_TRACK_ID;	}	MP4TrackId trackId = MP4AddAudioTrack(mp4File, 		samplesPerSecond, samplesPerFrame, mp4AudioType);	if (trackId == MP4_INVALID_TRACK_ID) {		fprintf(stderr,				"%s: can't create audio track\n", ProgName);		return MP4_INVALID_TRACK_ID;	}	if (MP4GetNumberOfTracks(mp4File, MP4_AUDIO_TRACK_TYPE) == 1) {		MP4SetAudioProfileLevel(mp4File, 0xFE);	}	int32_t i;	int32_t aviFrameSize;	int32_t maxAviFrameSize = 0;	// determine maximum avi audio chunk size	// should be at least as large as maximum mp3 frame size	AVI_seek_start(aviFile);	i = 0;	while (AVI_set_audio_frame(aviFile, i, (long*)&aviFrameSize) == 0) {		if (aviFrameSize > maxAviFrameSize) {			maxAviFrameSize = aviFrameSize;		}		i++;	}	// allocate a large enough frame buffer	u_int8_t* pFrameBuffer = (u_int8_t*)malloc(maxAviFrameSize);	if (pFrameBuffer == NULL) {		fprintf(stderr,				"%s: can't allocate memory\n", ProgName);		MP4DeleteTrack(mp4File, trackId);		return MP4_INVALID_TRACK_ID;	}	AVI_seek_start(aviFile);	u_int32_t mp3FrameNumber = 1;	while (true) {		if (AVI_read_audio(aviFile, (char*)pFrameBuffer, 4) != 4) {			// EOF presumably			break;		}		mp3header = BytesToInt32(&pFrameBuffer[0]);		u_int16_t mp3FrameSize = MP4AV_Mp3GetFrameSize(mp3header);		int bytesRead =			AVI_read_audio(aviFile, (char*)&pFrameBuffer[4], mp3FrameSize - 4);		if (bytesRead != mp3FrameSize - 4) {			fprintf(stderr,					"%s: Warning, incomplete audio frame %u, ending audio track\n",				ProgName, mp3FrameNumber);			break;		}		if (!MP4WriteSample(mp4File, trackId, 		  &pFrameBuffer[0], mp3FrameSize)) {			fprintf(stderr,					"%s: can't write audio frame %u\n", ProgName, mp3FrameNumber);			MP4DeleteTrack(mp4File, trackId);			return MP4_INVALID_TRACK_ID;		}			mp3FrameNumber++;	}	return trackId;}MP4TrackId* AviCreator(MP4FileHandle mp4File, const char* aviFileName){	static MP4TrackId trackIds[3];	u_int8_t numTracks = 0;	avi_t* aviFile = AVI_open_input_file(aviFileName, true);	if (aviFile == NULL) {		fprintf(stderr,				"%s: can't open %s: %s\n",			ProgName, aviFileName, AVI_strerror());	} else {		if (AVI_video_frames(aviFile) > 0) {			trackIds[numTracks] = VideoCreator(mp4File, aviFile);			if (trackIds[numTracks] != MP4_INVALID_TRACK_ID) {				numTracks++;			}		}		if (AVI_audio_bytes(aviFile) > 0) {			trackIds[numTracks] = AudioCreator(mp4File, aviFile);			if (trackIds[numTracks] != MP4_INVALID_TRACK_ID) {				numTracks++;			}		}		AVI_close(aviFile);	}	trackIds[numTracks] = MP4_INVALID_TRACK_ID;	return trackIds;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -