live555目前最新版(0.75)的mediaServer只支持".m4e"格式的Elementary Stream fie,但并不支持串流mp4封装格式的文件,要串流mp4格式的文件一般都是结合FFmpeg进行,但是代码量稍大,这里使用一种较为简单的方法实现对mp4封装格式文件的串流。
其具体思路如下图:
即我们预先对mp4文件进行处理,解析出各个流,并单独存储它们(解析工具用'mp4creator -extract='),然后将解析出来的H.264文件再进行串流处理(最新版的live555支持H.264的串流),客户端可用VLC或者FFmpeg的ffplay进行串流播放。
具体实现为只需在DynamicRTSPServer.cpp文件中添加如下实现代码:
else if((strcmp(extension, ".mp4") == 0) || (strcmp(extension, ".m4v") == 0)) { NEW_SMS("MPEG-4 Video/Audio"); // get the info about file char * command = (char *) malloc(150 * sizeof (char)); memset(command,0,150*sizeof(char)); command = strcat(command, "mp4info "); command = strcat(command, fileName); command = strcat(command, " >temp "); puts(command); system(command); /////////////////////////////parsing code///////////////////////////////////////////// FILE * fTemp = fopen("temp", "r"),*temp = NULL; if (fTemp != NULL) { char c, ext[4]; ext[0] = '.'; ext[1] = 't'; ext[3] = '\0'; char * Word = (char *) malloc(100 * sizeof (char)); memset(Word,0,100 * sizeof(char)); int flagLine = 0, lineCount = 0, flagWord = 0, wordCount = 0, i = 0, flagCodec = 0, streamCount = 1; while (!feof(fTemp)) { if (lineCount != 3) { c = getc(fTemp); } if (flagLine == 1) { flagLine = 0; if ((c > 48) && (c < 59)) {// get inside the stream numbers only ... flagWord = 1; while ((c != '\n') && (!feof(fTemp))) { c = getc(fTemp); if (flagWord == 1) { i = 0; while ((c != ' ') && (c != '\t') && (!feof(fTemp))) { Word[i] = tolower(c); i++; c = getc(fTemp); } Word[i] = '\0'; if ((strcmp("video", Word) == 0) || (strcmp("audio", Word) == 0)) { flagCodec = 1; wordCount = 0; int i; for (i = 0; i < 100; i++) { Word[i] = '\n'; } ext[2] = '0' + streamCount; strcpy(Word, "mp4creator -extract="); Word[20] = streamCount + 48; Word[21] = ' '; Word[22] = '\0'; Word = strcat(Word,fileName); puts(Word); command = strcpy(command, fileName); command = strcat(command, ext); temp = fopen(command,"r"); if(temp == NULL) { env<< "creating files"; system(Word); } puts(command); streamCount++; } if ((flagCodec == 1) && (wordCount == 1)) { if (strcmp("h264", Word) == 0) { // printf("error cant play H.264 files."); // return 0; NEW_SMS("H.264 Video"); OutPacketBuffer::maxSize = 100000; // allow for some possibly large H.264 frames sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, command, reuseSource)); } } if ((flagCodec == 1) && (wordCount == 2)) { flagCodec = 0; printf("Flagged - %s line: %d\n", Word, lineCount); ///////////////////////////////enter the code here//////////////////////////////// if (strcmp("aac", Word) == 0) { puts("aac found"); sms->addSubsession(ADTSAudioFileServerMediaSubsession ::createNew(env, command, reuseSource)); puts(ext); } else if (strcmp("simple", Word) == 0) { puts("m4e found"); sms->addSubsession(MPEG4VideoFileServerMediaSubsession ::createNew(env,command, reuseSource)); puts(ext); } else if (strcmp("h264", Word) == 0) { puts("m4e found"); puts(ext); } else if (strcmp("amr", Word) == 0) { puts("amr found"); puts(ext); } } flagWord = 0; ////////// the word flag is reset } if ((c == '\t') || (c == ' ')) { wordCount++; flagWord = 1; // the word flag set for getting next word. } } flagWord = 0; wordCount = 0; goto out; } } out: if (c == '\n') { lineCount++; if (lineCount > 2) { flagLine = 1; } } } } else { printf("the file not found"); return 0; } }
参考代码:http://sourceforge.net/projects/live555mp4/
附:
1.上述代码中用到两个工具程序mp4info.exe和mp4creator.exe,下载地址为:
http://download.csdn.net/detail/c_m_deng/4625514,http://download.csdn.net/detail/c_m_deng/4625522
2.关于live555最新版(2012.10.04)的下载地址及VC++6.0编译参考前一篇文章