Project1
标题:
FFMPEG视屏播放0.5求测试
[打印本页]
作者:
yangff
时间:
2011-9-11 19:45
标题:
FFMPEG视屏播放0.5求测试
本帖最后由 yangff 于 2011-9-12 00:44 编辑
= =技术区连只鸟都没有……
让我感觉压力很大所以就在水区又发了一份,
求测试各种分辨率
=v=
把分辨率和FPS一起丢上来吧0 0·
支持格式繁多,基本上你能找到的都支持,某些蛋疼的特殊格式除外
不具备实用价值,仅供参考,使用前请阅读LGPL的协议!
播放成功,原来那些奇怪的灰度或者是绿色黄色都正常了!!!
测试结果640*480以下都是满帧
800*600开始掉了
1024*768只能勉强用了
1200*720蛋都碎了
10000*10000你开的了这么大 的bitmap??
可以完美嵌入Bitmap
暂时不支持音轨。帧率自行协调
貌似最开头一段有点问题大概0.2s左右……?
DLL编译+演示下载(GUN C)
http://ftp.66rpg.com/yangff/RMPlayer.part1.rar
http://ftp.66rpg.com/yangff/RMPlayer.part2.rar
[attach]78808[/attach]
class Font
def marshal_dump;end
def marshal_load(obj);end
end
class Bitmap
# 传送到内存的API函数
RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
def _dump(limit)
data = "rgba" * width * height
RtlMoveMemory_pi.call(data, address, data.length)
[width, height, Zlib::Deflate.deflate(data)].pack("LLa*") # 压缩
end
def self._load(str)
w, h, zdata = str.unpack("LLa*"); b = new(w, h)
RtlMoveMemory_ip.call(b.address, Zlib::Inflate.inflate(zdata), w * h * 4); b
end
# [[[bitmap.object_id * 2 + 16] + 8] + 16] == 数据的开头
#
def address
buffer, ad = "xxxx", object_id * 2 + 16
RtlMoveMemory_pi.call(buffer, ad, 4); ad = buffer.unpack("L")[0] + 8
RtlMoveMemory_pi.call(buffer, ad, 4); ad = buffer.unpack("L")[0] + 16
RtlMoveMemory_pi.call(buffer, ad, 4);
return buffer.unpack("L")[0]
end
end
module RMPlayer
REG=Win32API.new("rmplayer","RegMovie","ip","i")
GNF=Win32API.new("rmplayer","NextFrame","ii","i")
CLM=Win32API.new("rmplayer","CloseMovie","ii","i")
def self.reg(a,s)
@a=a
@s=s
@h=REG.call(@a,s)
end
def self.next
GNF.call(@a,@h)
end
end
class RMP < Bitmap
def initialize(w,h,s)
super(w,h)
RMPlayer.reg(address,s)
end
def next
RMPlayer.next
end
end
@rmp=RMP.new(352,270,"haha.flv")
@v=Viewport.new(0,0,640,480)
@v.z=99
@s=Sprite.new(@v)
@s.z=99
@s.bitmap=@rmp
while true
@rmp.next
Graphics.update
end
复制代码
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
#include <Windows.h>
#include "libavutil/avstring.h"
#include "libavformat/avformat.h"
//#include "libavformat/rtsp.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
#include "libavcodec/opt.h"
#include <libavcodec/avcodec.h>
AVFormatContext *pFormatCtx;
int i, videoStream;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame;
AVFrame *pFrameRGB;
int numBytes;
uint8_t *buffer;
int __declspec(dllexport) RegMovie(int pBitmap,char * src)
{
avcodec_init() ;
av_register_all();
pFormatCtx = avformat_alloc_context();
if(av_open_input_file(&pFormatCtx,src, NULL, 0, NULL)!=0)return -1;// Couldn't open file
if(av_find_stream_info(pFormatCtx)<0) return -2;// Couldn't find stream information
//dump_format(pFormatCtx, 0, src, false);
videoStream=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
//if(&pFormatCtx->streams->codec.codec_type==CODEC_TYPE_VIDEO)
if ((pFormatCtx->streams[i]->codec->codec_type)==AVMEDIA_TYPE_VIDEO)
{
videoStream=i;
break;
}
if(videoStream==-1)
return -3; // Didn't find a video stream
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
return -4; // Codec not found
if(pCodec->capabilities & CODEC_CAP_TRUNCATED)
pCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
if(avcodec_open(pCodecCtx, pCodec)<0)
return -5; // Could not open codec
pFrame=avcodec_alloc_frame();
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)
return -6;
// Determine required buffer size and allocate buffer
numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
pCodecCtx->height);
buffer=malloc(numBytes);//new uint8_t[numBytes];
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
return 0;
}
int GetNextFrame(AVFormatContext *pFormatCtx, AVCodecContext *pCodecCtx,
int videoStream, AVFrame *pFrame)
{
static AVPacket packet;
static int bytesRemaining=0;
//static uint8_t *rawData;
static int fFirstTime=1;
int bytesDecoded;
int frameFinished;
// 我 们第一次调用时,将 packet.data 设置为NULL指明它不用释放了
if(fFirstTime)
{
fFirstTime=0;
packet.data=NULL;
}
// 解码直到成功解码完整的一帧
while(1)
{
// 除非解码完毕,否则一直在当前包中工作
while(bytesRemaining > 0)
{
// 解码下一块数 据
bytesDecoded=avcodec_decode_video2(pCodecCtx, pFrame,
&frameFinished, &packet);
// 出错了?
if(bytesDecoded < 0)
{
fprintf(stderr, "Error while decoding frame\n");
return 0;
}
bytesRemaining-=bytesDecoded;
// 我们完成当前帧了吗?接着我们返回
if(frameFinished)
return 1;
}
// 读取下一包,跳过所有不属于这个流的包
do
{
// 释放旧的包
if(packet.data!=NULL)
av_free_packet(&packet);
// 读取新的包
if(av_read_packet(pFormatCtx, &packet)<0)
goto loop_exit;
} while(packet.stream_index!=videoStream);
bytesRemaining=packet.size;
}
loop_exit:
// 解码最后一帧的余下部分
bytesDecoded=avcodec_decode_video2(pCodecCtx, pFrame,
&frameFinished, &packet);
// 释放最后一个包
if(packet.data!=NULL)
av_free_packet(&packet);
return frameFinished!=0;
}
void frame(int iHeight,int iWidth,uint8_t *iYuvBuf,AVFrame *pFrame)
{
int i,j,k;
for(i=0;i<iHeight;i++)
memcpy(iYuvBuf+iWidth*i, pFrame->data[0]+pFrame->linesize[0]*i,iWidth);
for(j=0;j<iHeight/2;j++)
memcpy(iYuvBuf+iWidth*i+iWidth/2*j,pFrame->data[1]+pFrame->linesize[1]*j,iWidth/2);
for(k=0;k<iHeight/2;k++)
memcpy(iYuvBuf+iWidth*i*2+iWidth/2*k, pFrame->data[2]+pFrame->linesize[2]*k, iWidth/2);
}
int __declspec(dllexport) NextFrame(int Bitmap,int playerHandle)
{
int * pBitmap=(int *)Bitmap;
if (GetNextFrame(pFormatCtx, pCodecCtx, videoStream, pFrame))
{
//struct SwsContext * img_convert_ctx;
//img_convert_ctx=sws_getContext( pCodecCtx->width/12, pCodecCtx->height/12,PIX_FMT_RGB32,pCodecCtx->width,pCodecCtx->height,PIX_FMT_YUV420P,2,NULL,NULL,NULL);
uint8_t *data = malloc (3*pCodecCtx->width*pCodecCtx->height);
uint8_t *src[3]= {data, data+pCodecCtx->width*pCodecCtx->height, data+pCodecCtx->width*pCodecCtx->height+pCodecCtx->width*pCodecCtx->height};
//int stride[3]={pCodecCtx->width, pCodecCtx->width, pCodecCtx->width};
//sws_scale(img_convert_ctx,(const uint8_t* const*)pFrame->data,pFrame->linesize,0,pCodecCtx->height,src,stride);
int p=0;
int r,g,b=0;
double y,u,v;
int off=pCodecCtx->width*pCodecCtx->height;
int off1=pCodecCtx->width*pCodecCtx->height*1;
frame(pCodecCtx->height,pCodecCtx->width,data,pFrame);
//pBitmap[pCodecCtx->width*pCodecCtx->height-1]=0xffffaaff;
for (int i=pCodecCtx->height-1;i>=0;i--){
for (int j=0;j<pCodecCtx->width;j++)
{ //if (i*pCodecCtx->width+j<pCodecCtx->height*pCodecCtx->width)
pBitmap[p]=0xff000000 ;
y=(double)src[0][i*pCodecCtx->width+j];//pFrame->pp;//data[0][p+off];
u=(double)src[1][(i/2*pCodecCtx->width+j)/2];//pFrame->pp;//data[0][p+off1];
v=(double)src[2][(i/2*pCodecCtx->width+j)/2];//pFrame->pp//data[0][p+off1+off];
r=(int)(1.164f*(y-16)+1.596f*(v-128));
g=(int)(1.164f*(y-16)-0.813f*(v - 128) - 0.391f*(u - 128));
b=(int)(1.164f*(y-16)+2.018f*(u - 128));
if (r>255) r=255; if (r<0) r=0;
if (g>255) g=255; if (g<0) g=0;
if (b>255) b=255; if (b<0) b=0;
pBitmap[p]|= b; //b
pBitmap[p]|= g << 8; // g
pBitmap[p]|= r << 16; // r
// | data[((j+i*pCodecCtx->width+pCodecCtx->width*pCodecCtx->height) << 8)];// | data[((j+i*pCodecCtx->width+pCodecCtx->width*pCodecCtx->height*2) << 16)] | (0xff << 24);
p++;
}}
free(data);
return 1; }
return -1;
}
int __declspec(dllexport) CloseMovie(int pBitmap,int playerHandle)
{
}
复制代码
作者:
fux2
时间:
2011-9-11 22:28
你妹的乱触。
作者:
亿万星辰
时间:
2011-9-11 22:32
代码为什么少了第一行
作者:
yangff
时间:
2011-9-12 00:44
更新范例……附带奇妙的福利
作者:
流星的瞬间
时间:
2012-12-15 18:07
这是什么?VX视频播放器?
作者:
咕噜
时间:
2012-12-15 18:14
{:2_273:}播放器,快播 {:2_251:}
欢迎光临 Project1 (https://rpg.blue/)
Powered by Discuz! X3.1