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编译参考前一篇文章