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