MPV 提供了丰富的各种接口(姑且这么叫吧),其中有个功能是截图功能,使用时,笔者还是颇费了 一番功夫,或许是源于对C语言理解的肤浅。闲话少说,下面先给出文档原文,然后给出代码。


screenshot-raw []
Return a screenshot in memory. This can be used only through the client API. The MPV_FORMAT_NODE_MAP returned by this command has the w, h, stride fields set to obvious contents. The format field is set to bgr0 by default. This format is organized as B8G8R8X8 (where B is the LSB). The contents of the padding X are undefined. The data field is of type MPV_FORMAT_BYTE_ARRAY with the actual image data. The image is freed as soon as the result mpv_node is freed. As usual with client API semantics, you are not allowed to write to the image data.

The stride is the number of bytes from a pixel at (x0, y0) to the pixel at (x0, y0 + 1). This can be larger than w * 4 if the image was cropped, or if there is padding. This number can be negative as well. You access a pixel with byte_index = y * stride + x * 4 (assuming the bgr0 format).

The flags argument is like the first argument to screenshot and supports subtitles, video, window.

注:其他截图功能比较简单,例如保存到文件中这种方式,我们是要放到内存里。

这里的核心部分是对 MPV_FORMAT_NODE_MAP 的理解,我当时还是仔细研读了一下,现在不想再读了。直接给出处理代码部分,请大家对照代码在再结合上文进行理解。

     public Bitmap getScreenShotBmp(string flags){if (_mpvHandle == IntPtr.Zero) return null;Bitmap bmp;int w=0, h=0, stride=0;//获得截图数据,byte数组格式byte[] imgdat = getScreenShotDat(ref w,ref h, ref stride, flags);//将byete数组数据转化成图像bmp=imgLittleKit.setImagePixel(imgdat, w, h,stride/w, PixelFormat.Format32bppRgb);return bmp;}

getScreenShotDat 源代码,也是本文的核心部分

        //flags:subtitles, video, window// subtitles and video works well, window :  messy picture got ???public unsafe byte[] getScreenShotDat(ref int imgW,ref int imgH,ref int stride ,string flags="video"){wrong code!//if (imgW <= 0 || imgH <= 0) return null;/byte[] imgDat=null ;if (_mpvHandle == IntPtr.Zero) return null;try{mpv_node mpvnode = new mpv_node();DoMpvCommandRet(&mpvnode, "screenshot-raw", flags);//下面是测试代码....//mpv_node *mpvnode;//mpvnode = lpBuffer;//switch (mpvnode.u.list[0].values[0].u.ba//    .//{//    case mpv_format.MPV_FORMAT_BYTE_ARRAY://    case mpv_format.MPV_FORMAT_DOUBLE://    case mpv_format.MPV_FORMAT_FLAG://    case mpv_format.MPV_FORMAT_INT64://    case mpv_format.MPV_FORMAT_NODE://        Console.WriteLine("The return format is ...");//        break;//    case mpv_format.MPV_FORMAT_NODE_ARRAY://        Console.WriteLine("The return format is MPV_FORMAT_NODE_ARRAY...");//        break;//    case mpv_format.MPV_FORMAT_NODE_MAP://        Console.WriteLine("The return format is MPV_FORMAT_NODE_MAP...");//        break;//    case mpv_format.MPV_FORMAT_NONE://    case mpv_format.MPV_FORMAT_OSD_STRING://    case mpv_format.MPV_FORMAT_STRING://        break;//    default://        Console.WriteLine("The return format is an exception...");// 如果没有识别到任何命令,输出一个警告信息//        break;//}//based on the debug , find the following//Int64 imgW, imgH ;//获得图像的长宽灯关键数据,代码核心部分// if ((int)mpvnode.u.list != 0X0){imgW = (int)mpvnode.u.list[0].values[0].u.int64;//imgH = (int)mpvnode.u.list[0].values[1].u.int64;//stride = (int)mpvnode.u.list[0].values[2].u.int64;//Int64 uknownVal;uknownVal = mpvnode.u.list[0].values[3].u.int64;////from https://www.cnblogs.com/ljybk/p/9381907.html//C#中,把void*转换为byte// get the image data ;uint imgDatLen = (uint)mpvnode.u.list[0].values[4].u.ba->size;imgDat = new byte[imgDatLen];using (UnmanagedMemoryStream tempUMS = new UnmanagedMemoryStream((byte*)mpvnode.u.list[0].values[4].u.ba->data, imgDatLen)){tempUMS.Read(imgDat, 0, imgDat.Length);}_mpvFreeNodeContents(&mpvnode);}}catch (Exception ex){MessageBox.Show(ex.Message);}return imgDat;}

setImagePixel 代码,该代码参考了网络代码。

        public static Bitmap setImagePixel(byte[] srcImgDat, int iWidth, int iHeight, int pxlWidth, PixelFormat pxFmt){Bitmap dest = new Bitmap(iWidth, iHeight);//if (iWidth % 4 != 0)//{//    iWidth = iWidth - (iWidth % 4);//}Rectangle rect = new Rectangle(0, 0, iWidth, iHeight);System.Drawing.Imaging.BitmapData bmpData = dest.LockBits(rect,System.Drawing.Imaging.ImageLockMode.ReadWrite, pxFmt);IntPtr dstIPtr = bmpData.Scan0;int iBytes = iWidth * iHeight * pxlWidth;//bmpData.Scan0 = System.Runtime.InteropServices.Marshal.AllocHGlobal(iBytes);  //这句代码必须删除,否则会出现内存问题System.Runtime.InteropServices.Marshal.Copy(srcImgDat, 0, dstIPtr, iBytes);dest.UnlockBits(bmpData);return dest;}

有了上面的三个函数,就可以了实现截屏功能了,图像放在内存中。如果有不明白的朋友,可以留言。

注:上述代码仅支持彩色电影,黑白电影有问题,没有仔细思考,估计是图像格式不同造成的,处理应该简单,待本人研究后再做补充。

马拉孙 于 2021-05-08
北京泛五地区

视频播放开发笔记-获取MPV的视频内存方式截图相关推荐

  1. Android开发笔记——常见BUG类型之内存泄露与线程安全

    一.内存泄露 1.很抱歉,"XXX"已停止运行.OOM? 怎样才能让app报OOM呢?最简单的办法如下: Bitmap bt1 = BitmapFactory.decodeReso ...

  2. [开发笔记]-获取歌曲ID3信息

    ID3介绍: ID3,一般是位于一个mp3文件的开头或末尾的若干字节内,附加了关于该mp3的歌手,标题,专辑名称,年代,风格等信息,该信息就被称为ID3信息,ID3信息分为两个版本,v1和v2版. 获 ...

  3. iOS RTMP 视频直播开发笔记(4) ---- 视频清晰度 BP,EP,MP,HP

    iOS的Video参数中有一个叫做AVVideoProfileLevelKey的参数,说明太简单,只说了NSString, H.264 only,只好自己Google了. 既然是H.264专用参数,那 ...

  4. 微信小程序开发笔记—获取颜色十六进制值

    获取颜色十六进制值 十六进制颜色代码是在软件中设定颜色的代码,可以先查询以下目标颜色的RGB值,然后将三个值均转换成十六进制即是目标颜色的十六进制值.转换这里可以使用电脑计算器中的程序员模式.比如目标 ...

  5. iOS 开发笔记-获取某个APP素材

    有时候,我们看到别人的APP做得挺漂亮的,那么我们想查看该APP的图片素材,要怎么弄呢? 一.下载一个iTools,安装,与手机链接.点击应用,选择我们要查看的APP,选择备份,保存到桌面. 二.回到 ...

  6. Hololens2开发笔记-获取经纬度位置信息(unity)

    文章目录 环境 相关代码 效果展示 注意事项 环境 Hololen2 Windows 10 Unity 2019.4.19f1c1 Visual Studio 2019 MRTK 2.5.4 相关代码 ...

  7. js截屏 video_js获取video任意时间的画面截图

    js获取video任意时间的画面截图 更新时间:2019-04-16 09:12:00点击次数:1757次 首先就是要把视频加载出来,然后使用canvas.getContext('2d').drawI ...

  8. 海康摄像头开发笔记(一):连接防爆摄像头、配置摄像头网段、设置rtsp码流、播放rtsp流、获取rtsp流、调优rtsp流播放延迟以及录像存储

    文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/131679108 红胖子(红模仿)的博文大全:开发技术集合( ...

  9. Android开发笔记(一百二十五)自定义视频播放器

    视频播放方式 在Android中播放视频的方式有两种: 1.使用MediaPlayer结合SurfaceView进行播放.其中通过SurfaceView显示视频的画面,通过MediaPlayer来设置 ...

最新文章

  1. js 抛出异常 throw
  2. 定位的四个点怎么打_别被忽悠了,轮胎动平衡和四轮定位一定要区分清楚
  3. 大话程序猿眼里最全的高并发,快收藏!
  4. Windows API 第二篇 SHGetSpecialFolderPath
  5. PySide文档阅读笔记-第一个Qt for Python程序
  6. rsync和inotify实时同步配置 exclude排除多个文件夹
  7. 降序排序_排序简单,应用不易,使用Excel排序的几点建议
  8. vc6.0安装过程中出现的问题——解决
  9. 解读今年的 Google IO 2017
  10. 20130418定义全局变量
  11. HTML5 Canvas雨滴下落动画 超逼真
  12. 计算机函数语法,clickhouse 函数语法
  13. Java获取打印机打印图片
  14. 整理iOS9适配中出现的坑(图文)
  15. 引物设计-Primer6.0
  16. The Book of Qt4 : The Art of Building Qt Application 阅读笔记
  17. android设置主题背景为壁纸_Android 应用背景加载系统动态壁纸
  18. 排序算法——希尔排序的图解、代码实现以及时间复杂度分析
  19. 响应式设计的三个步骤
  20. 今天向大家推荐一款国产良心工具包 -- Hutool,让你的java变得更甜

热门文章

  1. 数理篇 - 高等数学小筑
  2. vscode html注释快捷键_最强编辑器 VSCode 系列之插件推荐【不定期更新】
  3. uni-app实现图片的上传和裁剪
  4. s18服务器维护,8月11日S15至S18服务器合服公告!
  5. java基础提升(六):缓冲流、转换流、序列化流、打印流
  6. 《Linux就该这么学》读书笔记
  7. 各种通信铁塔和机房类型介绍,别再傻傻分不清了
  8. 苹果尼玛 你在逗我么
  9. 南梦宫 拼图笔记 1.流畅的拖拽操作
  10. 使用Python模拟武侠小说中两派人的一场遭遇战。