debugly / ijkplayer

iOS/macOS/tvOS video player based on ijkplayer, using FFmpeg 6, support Metal、hw accel、HDR、ass subtitle effect...
GNU General Public License v2.0
114 stars 20 forks source link

可以提供一个实时获取AVFrame 或者 CVPixelBufferRef 的代理么 #44

Closed climlove closed 1 month ago

climlove commented 2 months ago

如图,这样我可以获取到播放画面,并做进一步的处理

climlove commented 2 months ago

甚至实时的UIimage 也是可以的

debugly commented 2 months ago

图呢? 你这个需求,当然可以满足。

climlove commented 2 months ago

没有图,写错了,我是说如标题所示,我希望播放器能有个代理函数能 给一个播放的当前帧。

climlove commented 2 months ago

比如在IJKMediaPlayback.h 提供一个代理可以让我获取到当前播放的帧

climlove commented 2 months ago

比如系统的AVPlayerItemVideoOutput 可以获取avplayer 播放的当前帧,我希望ijk也有这个功能

debugly commented 2 months ago

1、创建一个View实现 IJKVideoRenderingProtocol 协议;假设名字叫 MyRenderView 2、渲染这块不用自己去写,仍旧交给 IJK 负责,需要创建一个渲染View: UIView<IJKVideoRenderingProtocol> *render = [IJKInternalRenderView createMetalRenderView]; 把 render当作 MyRenderView的属性 3、实现 - (BOOL)displayAttach:(IJKOverlayAttach *)attach; 方法

- (BOOL)displayAttach:(IJKOverlayAttach *)attach{
//你需要的当前画面:attach.videoPicture
[self.render displayAttach:attach];
}

其中 IJKOverlayAttach 里的CVPixelBufferRef videoPicture; 属性就是你想要的当前播放帧,可以做进一步的处理。

4、创建播放器时使用 - (id)initWithMoreContent:(NSURL *)aUrl withOptions:(IJKFFOptions *)options withGLView:(UIView<IJKVideoRenderingProtocol> *)glView; 这个方法将 MyRenderView 传进去

debugly commented 2 months ago

你回复哪去了,有收到邮件,但是打开issue后看不到你的回复

climlove commented 2 months ago

我删掉了,我看到 IJKFFMoviePlayerController 里有一个 UIView* _glView; 我可以设法获得他的视频图片吗???我刚刚创建了一个 IJKVideoRenderingProtocol 的视图,但是运行的时候崩溃了,因为没有context;

debugly commented 2 months ago

_glView 实际上内部自动创建的,除非调用 - (id)initWithMoreContent:(NSURL )aUrl withOptions:(IJKFFOptions )options withGLView:(UIView *)glView 方法传进来。 你按照我说的步骤,指定可以的。

context 崩溃解决方法:

- (id)context 
{
    return nil;
}
climlove commented 2 months ago

}

我在demo里拖动进度条后 CVPixelBufferLockBaseAddress(pixelBufferRef, 0);报了Thread 1: EXC_BAD_ACCESS (code=1, address=0x8e7b78b50)的错误,但是pixelBufferRef又不是空的

debugly commented 2 months ago

这是野指针错误,你有必要管理好 pixelBufferRef 的内存,在处理前 Retain ,处理完毕 Release。

climlove commented 2 months ago
CVPixelBufferUnlockBaseAddress(pixelBufferRef, 0);
CVPixelBufferRelease(pixelBufferRef);  我这边调用释放的话,ff_play.c里int send = avcodec_send_packet(d->avctx, d->pkt); 就报错了
debugly commented 2 months ago

处理前调用 CVPixelBufferRetain 了吗

climlove commented 2 months ago

}. 如果是这么写的话,不会每次都崩溃,而是偶尔,反正还是有概率出现

climlove commented 2 months ago

我自己retain 概率崩溃,多次拉进度才可能出现,如果是retain 用完后release的话,第一次拉进度条就崩溃了。 不知道该如何了

climlove commented 2 months ago

我用avplayer 得到的CVPixelBufferRef ,不会有崩溃的情况,我觉得是不是ijk播放器输出前,你那边要处理下或者什么

debugly commented 2 months ago

提供个简易demo,我看下

climlove commented 2 months ago

我明天尝试给你一个demo 看看吧,原来的是在你的demo上做的实验

climlove commented 2 months ago

https://github.com/climlove/OPENGLDemo 这demo ijk库需要自己添加,你试下

debugly commented 2 months ago

我这运行时出错了:

image

climlove commented 2 months ago

直接把三个NO 改为NO_EXPOSURE_COMPENSATOR = 0 就可以了

debugly commented 2 months ago

运行起来了,可是你的demo里只是创建了playerView,没有按照我说的去做啊。ijk可以正常播放,你想让我看什么呢?

climlove commented 2 months ago

渲染是我这边渲染的,但是拖动进度条后有时候会崩溃

climlove commented 2 months ago

播放的视频是全景视频,所以我需要自己做渲染,播放器解码的话想使用ijk,但是拖动进度条的时候,有可能会崩溃。就是在处理CVPixelBufferRef的时候

debugly commented 2 months ago

1、当前环境复杂,崩溃不一定是IJK导致的,使用我的demo,改成你的全景视频拖动进度条是否崩溃? 2、将cvpixelbuffer 一通转换到opencv的image效率低,你确定播放时不卡顿?avplayer output跟opencv已经串起来了?

climlove commented 2 months ago

1.一开始就是在你的demo上 修改的,然后发现拖动进度条 会出现偶尔崩溃的情况,具体就在报错就在cvpixelbuffer的使用上面。2.将cvpixelbuffer 转成image 再转为cv:Mat 是目前无奈之举,如果能获取avframe 来转换效率应该更高,可是目前拿不到。