铁血丹心

 找回密码
 我要成为铁血侠客
搜索
查看: 2320|回复: 1

[通用] 在游戏中播放视频

[复制链接]
发表于 2013-7-5 02:09 | 显示全部楼层 |阅读模式

马上注册,结交更多侠友!

您需要 登录 才可以下载或查看,没有账号?我要成为铁血侠客

x
本帖最后由 weyl 于 2013-7-5 02:24 编辑

播放视频并不是什么难事,在游戏窗口中播放视频就有点麻烦了。实际上一个游戏并不需要很复杂的视频功能,只需能够播放或者跳过就可以了。

虽然sdl自己带了一个smpeg,不过说实话有点废。那么我们需要引入一些外部的库来实现更复杂的功能。

这几天试着给猪3增加了一个开头动画(山寨来的,不是原创,哪位熟悉动画制作的可以友情支援)。至于在游戏的窗口播放,现在找到了两个解决方案:

1. bass_dshow(xVideo)

这个也属于以前介绍过的bass音频库的插件之一,依赖bass和bassmix,本质是使用directx show,因此只能用于windows。
关键的问题在于,这个库的使用简单得有点过分。一般来说,我们想画个图,总要弄个内部结构先画上,然后把我们内部的图弄到游戏窗口上,但是xVideo完全不考虑这个,它直接抢占程序的窗口来放视频,而不管这个窗口的来历,这个窗口可以是一个Form,SDL窗口,甚至是带有OpenGL属性的窗口(这个太狠了)。


而简单地说,用xVideo的库来放一个视频,只需4到5个语句,常用的如下:
  1. xVideo_Init(0, 0);
  2. xVideo_StreamCreateFile 用来创建视频流
  3. xVideo_ChannelSetAttribute 设置音量,声道平衡等
  4. xVideo_ChannelGetInfo 可以获取视频的属性,如尺寸等
  5. xVideo_ChannelResizeWindow 设置视频的尺寸和位置
  6. xVideo_StreamFree
  7. xVideo_Free
复制代码
这个库公开的版本1.22是非商业应用免费,但是不支持回调。新的版本可以下载到未注册的,注册过的似乎已经不提供免费授权了。
在Windows上做游戏的话,推荐使用,因为简单有效。


2. ffmpeg

这个库只能用于解码,无法用于播放。一般编写播放器使用这个,做游戏用就过于复杂了。因为游戏用的视频一般不长,所以我这里用了一个很简单的方式,即先解码完整音频,再解码视频。注意,这只是一个偷懒的方案,并不是一个好的处理手段。

特别地,ffmpeg与bass结合播放音频,目前网络上的资料非常少见,至少我是没查到。以下代码是我自己摸索出来的:

初始化部分,音频视频都需要:
  1.   av_register_all();
  2.   if av_open_input_file(pFormatCtx, PChar(filename), nil, 0, nil) = 0 then
  3.   begin
  4.     av_find_stream_info(pFormatCtx);
  5. ..............................
复制代码
解码完整音频部分,原理是创建Push模式的音频流再向其中压入数据:
  1.   audioStream := -1;
  2.     for i := 0 to pFormatCtx.nb_streams - 1 do
  3.     begin
  4.       if pFormatCtx.streams[i].codec.codec_type = AVMEDIA_TYPE_AUDIO then
  5.       begin
  6.         audioStream := i;
  7.         break;
  8.       end;
  9.     end;
  10.     pCodecCtxA := pFormatCtx.streams[audioStream].codec;
  11.     pCodecA := avcodec_find_decoder(pCodecCtxA.codec_id);
  12.     avcodec_open(pCodecCtxA, pCodecA);
  13.     bufferA := av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE);
  14.     //创建push模式的bass音频流
  15.     A := BASS_StreamCreate(pCodecCtxA.sample_rate, pCodecCtxA.channels, 0, STREAMPROC_PUSH, nil);
  16.     //将找到的音频流解压并压入
  17.     while True do
  18.     begin
  19.       if av_read_frame(pFormatCtx, packet) < 0 then
  20.         break;
  21.       if (packet.stream_index = audioStream) then
  22.       begin
  23.         sizeA := AVCODEC_MAX_AUDIO_FRAME_SIZE;
  24.         avcodec_decode_audio2(pCodecCtxA, pSmallint(bufferA), sizeA, packet.Data, packet.size);
  25.         BASS_StreamPutData(A, bufferA, sizeA);
  26.       end;
  27.       av_free_packet(@packet);
  28.     end;
  29.     av_free(bufferA);
  30.     BASS_ChannelSetAttribute(A, BASS_ATTRIB_VOL, VOLUME / 100.0);
复制代码
上面的代码获得的音频流A就可以用bass播放了。
至于解码视频部分,网上的资料很多,配合SDL输出的非常多,配合opengl的比较少,其实关键的地方是转换格式用的那几个参数必须正确。

比如用SDL的YUV输出的话,最关键的两句是:
  1.             img_convert_ctx :=
  2.               sws_getContext(pCodecCtx.Width, pCodecCtx.Height, pCodecCtx.pix_fmt, pCodecCtx.Width,
  3.               pCodecCtx.Height, PIX_FMT_YUV420P, SWS_BICUBIC, nil, nil, nil);
  4.             sws_scale(img_convert_ctx, @pFrame.Data[0], @pFrame.linesize[0], 0, pCodecCtx.Height,
  5.               @pict.Data[0], @pict.linesize[0]);
复制代码
这个网上都说得很清楚,只是前面的指针可能会把人弄糊涂。

opengl用下面的语句:
  1.             img_convert_ctx :=
  2.               sws_getContext(pCodecCtx.Width, pCodecCtx.Height, pCodecCtx.pix_fmt, pCodecCtx.Width,
  3.               pCodecCtx.Height, PIX_FMT_RGB24, SWS_BICUBIC, nil, nil, nil);
  4.             sws_scale(img_convert_ctx, @pFrame.Data[0], @pFrame.linesize[0], 0, pCodecCtx.Height,
  5.               @pFrameRGB.Data[0], @pFrameRGB.linesize[0]);
  6.             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pCodecCtx.Width, pCodecCtx.Height,
  7.               0, GL_RGB, GL_UNSIGNED_BYTE, pFrameRGB.Data[0]);
复制代码
关键的地方是PIX_FMT_RGB24,GL_RGB这几个参数不能选错。
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。
发表于 2013-7-5 09:15 | 显示全部楼层
sws_getContext和sws_scale似乎是将yuv转成argb,效率奇差,其实本人觉得还是直接将yuv按进显存
【武侠.中国】铁血丹心论坛(大武侠):致力于推广和发展武侠文化,让我们一起努力,做全球最大的武侠社区。
可能是目前为止最好的金庸群侠传MOD游戏交流论坛,各种经典武侠游戏等你来玩,各种开源制作工具等你来实现你的游戏开发之梦。

本版积分规则

小黑屋|手机版|铁血丹心

GMT+8, 2024-5-3 14:00

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表