您的位置:首页 > 其它

视频转码之OSMF框架下的.f4f转化为.flv

2015-12-05 18:18 316 查看

OSMF框架:

即为开源多媒体框架(open source media frame),据老师介绍,它的一个好处就是可以在视频文件的头部预留一个区域,这个区域是使用者可以“私人定制”的,所以增强了对视频的控制,更加灵活;

下面介绍.f4f和.flv的格式:

flv的格式图解如下:



f4f的格式图解如下:



注:在f4f格式中,有固定的四个字节表示"mdat",而mdat的前边四个字节代表的是视频内容长度,比如 20 09 B4 B5,代表的十进制长度就是‭537506997‬,单位:bytes

见下图,会更加直观一些:



转换的思路:

根据把f4f文件的"mdat"作为标识符;首先入读f4f字节序列,搜索第一个6D646174(即为"mdat",因为可能有多个mdat),找到之后计算出视频内容的长度,进而可以确定视频内容序列在f4f文件中的位置;最后新建个一个flv文件,把flv固定的“头”与f4f文件中的视频内容拼在一起就ok啦。

Talk is cheep,show you the code:

需要注意的:

1.读文件时别读到string里边,因为表示形式会改变,比如:00-->30

2.时间主要消耗在字串搜索上边,一般情况下暴力搜索就可以,时间也可以忍受,但是如果处理高并发的情况(同时处理好多文件),就需要优化子串搜索了,代码里写了两个搜索函数,一个BF暴力的,一个sunday算法的

#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <pthread.h>
#include <math.h>
#include <string.h>
#define BYTE unsigned char
#define FLVHEAD_LEN 26
#define LETTER_MAX_LEN 256
#define MAXLINE 1024
long long getlen(int input[4])
{//将四个字节的16数进制转为一个10进制数,input中每一个元素代表一个字节
int fir=0,sec=0,mici=7;
long long res=0;
for(int i=0;i<4;i++)
{
fir=input[i]/16;
sec=input[i]%16;
//printf("%d %d ",fir,sec);
res+=fir*pow(16,mici)+sec*pow(16,mici-1);
//printf("%lld\n",res);
fir=0;sec=0;mici-=2;
}
return res;
}
int String2Bytes(unsigned char* szSrc, unsigned char* pDst, int nDstMaxLen)
{//将字符串转化为字节数组,便于将真正的16数写入文件

if(szSrc == NULL)
{
return 0;
}
int iLen = strlen((char *)szSrc);
if (iLen <= 0 || iLen%2 != 0 || pDst == NULL || nDstMaxLen < iLen/2)
{
return 0;
}

iLen /= 2;
// strupr((char *)szSrc);
for (int i=0; i<iLen; i++)
{
int iVal = 0;
unsigned char *pSrcTemp = szSrc + i*2;
sscanf((char *)pSrcTemp, "%02x", &iVal);
pDst[i] = (unsigned char)iVal;
}

return iLen;
}
int getIndex_BF(BYTE *S,long long S_len,BYTE *T,int pos)
{ // 返回子串T在主串S中第pos个字符之后的位置。若不存在,则函数值为0。
// 其中,T非空,1≤pos≤StrLength(S)。算法4.5
long long i,j;
i=pos;
j=0;
while(i<S_len&&j<4)
if(S[i]==T[j]) // 继续比较后继字符
{
++i;
++j;
}
else // 指针后退重新开始匹配
{
i=i-j+1;
j=0;
}
if(j=4)
return i-4;
else
return 0;
}

static int getIdex_Sunday(unsigned char *src, long long len_s,unsigned char *des)
{
int i, pos = 0;
int len_d;
int alphabet[LETTER_MAX_LEN] = {0};

if(src == NULL || des == NULL)
return -1;

//len_s = strlen(src);
len_d = 4;

for(i = 0; i < LETTER_MAX_LEN; i++)
alphabet[i] = len_d;

for(i = 0; i < len_d; i++)
alphabet[des[i]] = len_d - i - 1;

for(pos = 1; pos <= len_s - len_d; ) {
for(i = pos - 1; i - pos + 1 < len_d; i++) {
if(src[i] != des[i - pos + 1])
break;
}

if((i - pos + 1) == len_d)
return pos;
else
pos += alphabet[src[pos + len_d - 1]] + 1;
}

return -1;
}
int osmf_parse(unsigned char* buf,long long total_len,long long  *content_len,int* offset)
{
if(buf==NULL||total_len==0)
return 0;

BYTE flag[]="mdat";
int pos=0;
int len[4];     //存代表长度的字节

BYTE flvhead[]="464c5601050000000900000000";
BYTE flvbinary[FLVHEAD_LEN];
FILE* pf2 = fopen("out1-fast.flv","w+");

String2Bytes(flvhead,flvbinary,FLVHEAD_LEN);//hex2bytes

//pos=getIndex_BF(buf,total_len,flag,0);
pos=getIdex_Sunday(buf,total_len,flag)-1;

for(int i=0;i<4;i++)//获取长度字节数组
len[i]=buf[pos-4+i];

*content_len=getlen(len);
*offset=(int)(&buf[pos+4]-buf);

fwrite(flvbinary,FLVHEAD_LEN/2,1,pf2);
fwrite(&buf[pos+4],*content_len,1,pf2);
fclose(pf2);
return 1;
}

int main()
{
int offset=0;
long long conten_len=0;
FILE* pf = fopen("1.f4f","rb");

if (NULL==pf)
{
fprintf(stderr,"can not open the specified file ");
return 1;
}
fseek(pf,0,SEEK_END);
long long total_len = ftell(pf);
fseek(pf,0,SEEK_SET);
BYTE* pBuf = (BYTE*)calloc(total_len,sizeof(BYTE));
memset(pBuf,0,total_len);
long long get_len = total_len;
long long offsets = 0;
while (offsets<total_len)
{
int read_len = fread(pBuf+offsets,sizeof(char),get_len,pf);
offsets += read_len;
get_len -= read_len;
}
offsets=0;
fclose(pf);

osmf_parse(pBuf,total_len,&conten_len,&offset);

printf("%d %d ok",conten_len,offset);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: