EasyPlayer实现直播抓拍

EasyPlayer实现直播抓拍对于一个裸的RTSPURL,存放在播放列表上略显单调与枯燥。大家可以看到EasyPlayer在播放完视频后会保存一帧图片到列表上。那么这个功能是如何做到的呢?如果自己实现解码的话,比如使用ffmpeg解码,这种情况下,将视频帧解码,再编码成jpeg保存下来,应该不是什么难事。相信大多数播放器都是这样处理的。H264格式的视频码流=>解码=>YUV格式的视频帧=>压缩=>jpeg=>保存到

大家好,又见面了,我是你们的朋友全栈君。

对于一个裸的RTSP URL,存放在播放列表上略显单调与枯燥。大家可以看到EasyPlayer在播放完视频后会保存一帧图片到列表上。

EasyPlayer上的播放列表的缩略图

那么这个功能是如何做到的呢?
如果自己实现解码的话,比如使用ffmpeg解码,这种情况下,将视频帧解码,再编码成jpeg保存下来,应该不是什么难事。相信大多数播放器都是这样处理的。

H264格式的视频码流=>解码=>YUV格式的视频帧=>压缩=>jpeg=>保存到本地

但是如果我们用硬解码,很遗憾,安卓的硬解码并没有提供获取视频帧数据的功能,那又该如何实现呢?
有两种方法可以实现硬解码截屏

  • 单独创建只为抓图用的软解码器并用上面的方法来抓图
  • 直接获取TextureView的内容并保存

这里介绍下第二种方法。TextureView提供了一个getBitmap() 的方法,解释如下:

Returns a Bitmap representation of the content of the associated surface texture.

该方法提供了当前TextureView的渲染内容,作为一个Bitbmap对象返回。这样我们可以将这个Bitmap压缩成jpeg、png等格式并保存下来。Bitmap提供了compress 方法可以直接压缩。下面为从TextureView获取并存储Bitmap对象的方法:

public void takePicture(final String path) {
        try {
            if (mWidth <= 0 || mHeight <= 0) {
                return;
            }
            Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
            mSurfaceView.getBitmap(bitmap);
            saveBitmapInFile(path, bitmap);
            bitmap.recycle();
        } catch (OutOfMemoryError error) {
            error.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        }
    }

下面是将Bitmap保存成JPEG的方法,这里,同时会将缩略图保存在安卓系统的相册中,以便调用系统的选取图片的方法可以访问到:

    private void saveBitmapInFile(final String path, Bitmap bitmap) {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
            if (mScanner == null) {
                MediaScannerConnection connection = new MediaScannerConnection(getContext(),
                        new MediaScannerConnection.MediaScannerConnectionClient() {
                            public void onMediaScannerConnected() {
                                mScanner.scanFile(path, null /* mimeType */);
                            }

                            public void onScanCompleted(String path1, Uri uri) {
                                if (path1.equals(path)) {
                                    mScanner.disconnect();
                                    mScanner = null;
                                }
                            }
                        });
                try {
                    connection.connect();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                mScanner = connection;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (OutOfMemoryError error) {
            error.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

这里需要注意的是getBitmap函数的调用时机,

  • 首先一定要在TextureView创建之后调用。即在onSurfaceTextureAvailable方法回掉之后才能调用,否则Texture尚未创建,该函数会返回null 。
  • 不仅如此,还需要在视频播放之后再调用。否则TextureView所展示的内容为空,因此您保存的快照可能是纯黑色的。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/150346.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ringbuffer原理_git stash pop冲突

    ringbuffer原理_git stash pop冲突例子:ringbuffer.c实现#include<stdlib.h>#include<stdio.h>#include<string.h>#include”ringbuffer.h”voidringbuffer_init(structringbuffer*rb,uint8_t*pool,int16_tsize){if(rb==NULL){return;}rb-&g

    2022年9月4日
    3
  • HTML期末设计——代码篇[通俗易懂]

    HTML期末设计——代码篇[通俗易懂]事先声明这个网页设计也就是用了我学到的知识做的一个中规中矩的网页,可以给以后的大一新生们做个参考,和商业网站的效果肯定是没得比的,期望太高的可以关掉了,要严词批评我的请不要在我这说,当然,温柔的话,可以引入页效果图:<!DOCTYPEhtml><html> <head> <metacharset=”utf-8″> <title>欢迎来到香氛密语</title> <style>

    2022年6月14日
    30
  • 香农编码的matlab实现实验总结_香农编码C语言

    香农编码的matlab实现实验总结_香农编码C语言设计shannon编码方法,实现香农编码并算出编码效率实验三香农编码一、[实验目的]1、理解香农第一定理指出平均码长与信源之间的关系;2、加深理解香农编码具有的重要的理论意义。二、[实验环境]windowsXP,MATLAB7三、[实验原理]香农第一定理:设离散无记忆信源为Ss1P=p(s1)熵为H(S),其N次扩展信源为s2…..sqp(s2)….p(sq)SNα1=…

    2022年9月10日
    0
  • pta 列车调度_数据结构/PTA-列车调度/栈/数组

    pta 列车调度_数据结构/PTA-列车调度/栈/数组火车站的列车调度铁轨的结构如下图所示。两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?输入格式:输入第一行给出一个整数N(2≤…

    2022年7月26日
    8
  • 车牌检测STN:Spatial Transformer Networks

    车牌检测STN:Spatial Transformer Networks参考文献:MaxJaderberg,KarenSimonyan,AndrewZisserman,KorayKavukcuoglu.SpatialTransformerNetworks,2016.linkSpatialTransformerNetworks空间变换网络MaxJaderberg,KarenSimonyan,AndrewZisserman,Kor…

    2022年10月19日
    0
  • python3使用付费代理和ip池的维护「建议收藏」

    更新:在使用代理是如果频率过快返回的是‘{“code”:“3001”,“msg”:“提取频繁请按照规定频率提取!”}’不可将该msg添加到ip池中,故需要先判断返回状态。这一段时间爬取一些数据的时候遭到了封ip。免费的ip满足不了我的需求并且不是很稳定,所以选择的代理ip,我买了蘑菇代理一天2000ip,这些对于我的小爬爬就够了。记录了第一次使用代理ip的一些坎坷和经历,希望能够减少初学者的…

    2022年4月11日
    35

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号