#include<iostream>
using namespace std;
#include<windows.h>
#include<time.h>
#define SEARCH_BUFFER_SIZE 6536
const int PACKET_START_CODE = 0X000001BA;
const int PACKET_START_CODE_PREFIX = 0x00000001;
unsigned char packet_start_code_prefix[3] = {0x00 , 0x00 , 0x01};
unsigned char system_header_start_code[4] = {0x00 , 0x00 , 0x01 , 0xBB};
struct Frame
{
int offset;
int FrameNo;
int cap;
Frame()
{
offset = -1;
FrameNo = -1;
cap = -1;
}
}frame_s , frame_e;
//寻找当前偏移量的后一帧
Frame next(FILE *fp , int offset )
{
int i , k;
k = offset;
Frame frame;
unsigned char p , *buffer = (unsigned char *)malloc(SEARCH_BUFFER_SIZE);
if(NULL == buffer)
{
printf("分配内存错误\n");
exit(0);
}
while(1)
{
fseek(fp , k ,SEEK_SET); //指向以文件头为基准,偏移k个字节的位置
fread(buffer , 1 , SEARCH_BUFFER_SIZE , fp);
for(i = 0 ; i < SEARCH_BUFFER_SIZE ; ++i)
{
int start_code_tmp = *(buffer + i)<<24 | *(buffer + i + 1)<<16 | *(buffer + i + 2)<<8 | *(buffer + i + 3);
if(start_code_tmp == PACKET_START_CODE)
{
p = *(buffer + i + 4);
if((p>>6)&1 == 1)
{
frame.offset = (k + i);
frame.FrameNo = *(buffer+i+16)<<24 |
*(buffer+i+17)<<16 |
*(buffer+i+18)<<8 |
*(buffer+i+19);
break;
}
}
}//end of for
k += i;
if(i < SEARCH_BUFFER_SIZE)
{
break;
}
}//end of while
free(buffer);
buffer = NULL;
return frame;
}
//寻找当前偏移量的前一帧
Frame prev(FILE *fp , int offset )
{
int i , k;
bool flag = false;
Frame frame;
unsigned char p , *buffer = (unsigned char *)malloc(SEARCH_BUFFER_SIZE);
if(NULL == buffer)
{
printf("分配内存错误\n");
exit(0);
}
k = offset - SEARCH_BUFFER_SIZE;
if(k < 0)
k = 0;
while(1)
{
fseek(fp , k , SEEK_SET); //指向以文件头为基准,偏移k个字节的位置
fread(buffer , 1 , SEARCH_BUFFER_SIZE , fp);
for(i = 0 ; i < SEARCH_BUFFER_SIZE ; ++i)
{
int start_code_tmp = *(buffer + i)<<24 | *(buffer + i + 1)<<16 | *(buffer + i + 2)<<8 | *(buffer + i + 3);
if(start_code_tmp == PACKET_START_CODE)
{
p = *(buffer + i + 4);
if((p>>6)&1 == 1)
{
frame.offset = k + i;
frame.FrameNo = *(buffer+i+16)<<24 |
*(buffer+i+17)<<16 |
*(buffer+i+18)<<8 |
*(buffer+i+19);
flag = true;
//break;
}
}
}//end of for
k -= i;
if(k < 0)
k = 0; //防止超过文件头的范围
if(flag)
{
break;
}
}//end of while
free(buffer);
buffer = NULL;
return frame;
}
//帧的快速定位
Frame frame_alignment(FILE *fp , int want_no , int last_no)
{
int offset_w;
Frame nextframe , prevframe , tmp , frame , f_start , f_end;
f_start.FrameNo = 0; //初始化为第一帧
f_start.offset = 0;
f_end.FrameNo = last_no; //初始化为最后一帧
f_end.offset = frame_e.offset;
while(1)
{
offset_w = 1.0*(want_no - f_start.FrameNo)/(f_end.FrameNo - f_start.FrameNo) * (f_end.offset - f_start.offset) + f_start.offset; //求得大概的平均偏移位置
nextframe = next(fp , offset_w ); //求出偏移量位置的后一帧
prevframe = prev(fp , offset_w ); //求出偏移量位置的前一帧
if(want_no == nextframe.FrameNo)
{
frame.offset = nextframe.offset;
tmp = next(fp , frame.offset + 4 ); //+4跳过当前帧的起始部分,计算下一帧的偏移量,来计算帧的大小
frame.cap = tmp.offset - frame.offset;
break;
}
else if(want_no < prevframe.FrameNo) //所求帧号在prevframe的前面
{
f_end.FrameNo = prevframe.FrameNo;
f_end.offset = prevframe.offset;
}
else if(want_no > nextframe.FrameNo) //所求帧号在nextframe的后面
{
f_start.FrameNo = nextframe.FrameNo;
f_start.offset = nextframe.offset;
}
else
{
frame.offset = prevframe.offset;
tmp = next(fp , frame.offset + 4 );
frame.cap = tmp.offset - frame.offset;
break;
}
}//end of while
//fclose(fp);
return frame;
}
//解析PS流文件
int pes_to_video( FILE *fp)
{
if(NULL == fp)
return -1;
FILE *fpd;
unsigned char *p;
char videofile[20];
int size , rdsize , FrameNo , offset , curr;
unsigned char *buf = (unsigned char *)malloc(1880*1024);
strcpy(videofile , "test.mp4");
fpd = fopen( videofile, "wb" );
if(NULL == fpd)
{
return -1;
}
size = 0;
offset = 0;
curr = 0;
printf("正在处理中......\n");
//freopen("output4.txt" , "w" , stdout);
while(1)
{
if(size <= offset)
{
offset = 0;
size = 0;
}
else if(0 < offset && offset < size)
{
size -= offset;
memmove( buf , offset + buf , size ); //缓冲区内容往前移动
//void *memmove( void* dest, const void* src,size_tcount );
offset = 0;
}
if(!feof(fp) && size < sizeof(buf))
{
rdsize = fread( buf+size, 1, sizeof(buf)-size, fp ); //读取文件内容存储在缓冲区的后面,返回实际读取到的数目
size += rdsize;
}
//if(feof(fp)) //如果遇到文件结束,则函数feof返回值为非零值
//{
// printf("It is the end of the file!\n");
//}
if(size <= 0)
break;
p = offset + buf;
//判断PES包的起始码的前缀
while(p[0] != 0 || p[1] != 0 || p[2] != 0x01 || ( ( p[3] & 0xe0 ) != 0xe0 && ( p[3] & 0xe0 ) != 0xc0 ) )
{
//if( *((int*)p) == PACKET_START_CODE)
int start_code_tmp = *p<<24 | *(p + 1)<<16 | *(p + 2)<<8 | *(p + 3);
if(start_code_tmp == PACKET_START_CODE)
{
if((p[4]>>6)&1 == 1)
{
FrameNo = *(p+16)<<24 | *(p+17)<<16 | *(p+18)<<8 | *(p+19); //获取帧号
//printf("帧号:%d, 相对于文件头的偏移量:%d\n", FrameNo , curr);
frame_e.offset = curr; //帧的偏移量
if(1 == FrameNo)
{
frame_s.offset = 0;
frame_s.cap = curr;
frame_s.FrameNo = 0;
}
}
}
++offset;
p = offset + buf;
++curr;
}//end of while
if(memcmp(p , packet_start_code_prefix , sizeof(packet_start_code_prefix)) != 0)
{
fprintf(stderr , "The PES packet is not complete!\n");
}
p = offset + buf;
unsigned short len = (p[4]<<8) | p[5]; //PES packet length
if(buf + size < p + 6 + len)
{
if(feof(fp)) //文件结束
{
printf("It is the end of the file!\n");
break;
}
continue;
}
offset += 6; //跳过开始部分
p = offset + buf;
unsigned char PES_header_data_length = p[2]; //PES header data length
offset += 3; //跳过PTS、DTS、ESCR等标志位
p = offset + buf;
if(fpd)
{
fwrite(p + PES_header_data_length, 1, len - 3 - PES_header_data_length, fpd);
}
offset += len - 3; //指向下一个PES的起始地址
curr += len + 6; //跳过数据结构部分
size -= offset;
memmove(buf, offset + buf, size);
offset = 0;
p = offset + buf;
}//end of while
frame_e.cap = curr - frame_e.offset; //最后一帧的大小
fclose(fpd);
free(buf);
buf = NULL;
printf("处理完成!\n");
return 1;
}
void main()
{
//freopen("input.txt" , "r" , stdin); //读数据
//freopen("output.txt" , "w" , stdout);
FILE *fp;
int select , num , i , j , buffer_size , file_length;
long bigin , end;
char fname[500];
Frame frame;
printf("请输入文件来源:");
gets(fname);
//strcpy(fname , "D:\\stage 1\\人脸.mp4");
fp = fopen(fname, "rb");
if(NULL == fp)
{
printf("打开文件失败!\n");
exit(0);
}
fseek(fp, 0, SEEK_END); //指向以文件尾为基准,偏移0个字节的位置
file_length = ftell(fp); //用于得到文件位置指针当前位置相对于文件首的偏移字节数,即得到一个文件的长度
buffer_size = file_length>>2;
i = file_length - buffer_size;
unsigned char *buffer = (unsigned char *)malloc(buffer_size);
if(NULL == buffer)
{
fclose(fp);
printf("分配内存错误\n");
exit(0);
}
fseek(fp , i , SEEK_SET); //指向以文件头为基准,偏移i个字节的位置
fread(buffer , sizeof(char) , buffer_size , fp);
for(j = 0 ; j < buffer_size ; ++j)
{
int start_code_tmp = *(buffer + j)<<24 | *(buffer + j + 1)<<16 | *(buffer + j + 2)<<8 | *(buffer + j + 3);
没有合适的资源?快使用搜索试试~ 我知道了~
ps_packet_parse.rar_mpeg ps_ps h264_ps_packet_parse_ps流 解析_ps流解析
共17个文件
manifest:2个
pdb:2个
exe:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
5星 · 超过95%的资源 1 下载量 65 浏览量
2022-07-13
19:50:59
上传
评论
收藏 2.4MB RAR 举报
温馨提示
自己编写的一个PS流文件解析库,用户输入一个PS流多媒体文件的路径,然后对PS流进行分析,解析出原始的视频信息并保存下来,可以使用elecard进行播放, 还能够根据帧号进行快速的定位,输出帧号的偏移量、大小以及视频帧的高度、宽度等信息,以及调试通过,在分析PS流时非常有用。
资源推荐
资源详情
资源评论
收起资源包目录
ps_packet_parse.rar (17个子文件)
ps_packet_parse
ps_packet_parse.ncb 8.1MB
ps_packet_parse.suo 8KB
ps_packet_parse.sln 911B
Debug
ps_packet_parse.exe 42KB
ps_packet_parse.ilk 359KB
ps_packet_parse.pdb 635KB
ps_packet_parse
ps_packet_parse.vcproj 4KB
ps_packet_parse.vcproj.HIK.liuzhiwei.user 1KB
ps_packet_parse.cpp 10KB
Debug
ps_packet_parse.obj 62KB
ps_packet_parse.exe.embed.manifest.res 728B
BuildLog.htm 15KB
ps_packet_parse.exe.intermediate.manifest 621B
ps_packet_parse.exe.embed.manifest 663B
vc90.pdb 252KB
vc90.idb 443KB
mt.dep 65B
共 17 条
- 1
资源评论
- redelz2022-08-11资源质量不错,和资源描述一致,内容详细,对我很有用。
御道御小黑
- 粉丝: 57
- 资源: 1万+
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功