android 多媒体框架中mediaplay与opencore的衔接调用过程

【硬件开源实战】STM32G070RBT6开发板从设计到避坑全解析 本文全面解析了STM32G070RBT6开发板从硬件设计到避坑的实战经验。详细介绍了电源设计、时钟电路、PCB布局等关键环节,分享了成本控制、焊接测试、软件开发和外设驱动的实用技巧,帮助开发者高效完成项目开发。 阅读详情

本文从代码的角度来分析Android多媒体框架中mediaplay是如何调用opencore的。
一.摘要:
对于Android 多媒体框架,Google 在 Android 2.2中就已经实现了stagefright,但还是保留了opencore;
在新推出的2.3版本中,正式抛弃了opencore,而采用stagefright。网上关于Android opencore架构的文章有很多,例如下面的链接:
http://www.360doc.com/content/10/0207/22/155970_15398760.shtml。
但大都是基于框架的,而没有更加细致的给出代码的实现过程,
本文从MediaPlayer::setDataSource开始,分析一下整个opcncore的初始化过程。

二. 引子:
在播放一个视频文件的时候,往往会这样做:
第一步,创建一个MediaPlayer对象;
第二步,依次调用MediaPlayer的setDataSource,prepare,start函数;

本文仅仅分析setDataSource(opencore的初始化就是在这个函数中完成的)。
三. 代码分析:
1.  MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length):
当我们在java层调用setDataSource函数时,最终,它会通过jni调用到C++层的MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)函数。它的实现如下:
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length) ;
  1).getMediaPlayerService()  
        1.1   getService(String16("media.player")
  2).  service->create(getpid(), this, fd, offset, length)
        2.1  c = new Client, //这是一个MediaPlayerService::Client对象,参考MediaPlayerService类图
        2.2  c->setDataSource(fd, offset, length)
               getPlayerType
               sp<MediaPlayerBase> p = createPlayer(playerType);  // 真正的是实例PVPlayer, MidiFile or VorbisPlayer
                   android::createPlayer(playerType, this, notify)
                        sp<MediaPlayerBase> p;
                        case 1: p = new PVPlayer();  // defined media/PVPlayer.h
                        case 2: p = new MidiFile();   // defined libmediaplayerservice/PVPlayer.h
                        case 3: p = new VorbisPlayer();// same as MidiFile

                        case 4: p = new stagefright;   // 2.2开始加入的,2.3中就彻底用它了。


    3). setDataSource(player):保存player的引用到MediaPlayer中.

以上三步,简要分析如下:
首先. 得到MediaPlayerService;
其次. 通过MediaPlayerService这个service来创建Client,再通过Client去创建Player(即调用createPlayer函数),事实上,创建的真正的是实例PVPlayer, MidiFile or VorbisPlayer,这就是opencore于mediaplayer的真正的唯一的桥梁。
最后. 通过调用setDataSource(这个是MediaPlayer类的函数)就创建的适配层的实例保存在MediaPlayer类的成员对象mPlayer中(详见setDataSource函数)。

 

2. PVPlayer的初始化:

  1)相关文件分布:
     既然createPlayer(playerType)函数中最创建PVPlayer(即调用new PVPlayer()),那么,就有必要看一下PVPlayer的构造的实现:
     PVPlayer的头文件是PVPlayer.h,路径为:base/include/media,而实现是在Playerdriver.cpp中,路径为:opencore/android.
     从这个小小的文件分布来看,也能得出PVPlayer是衔接C++层的mediaserver与opencore的桥梁。
  2)然而,为什么头文件和实现不是相同的前缀名呢?
     答:看Playerdriver.cpp的代码就知道,原来,最终的与opencore打交道的任务都落在了Playerdriver这个类上,
     而它也是PVPlayer类的一个数据成员。所以,为了与上层的MediaPlayer(要注意,PVPlayer类是MediaPlayer类的数据成员->其实是sp<IMediaPlayer>       mPlayer,这里,因为PVPlayer继承了sp<IMediaPlayer>)衔接,头文件取名为PVPlayer; 另外,真正与opencore 打交道的是Playerdriver,所以,实现的Cpp文件就是Playerdriver.cpp了。笔者认为,为了更加代码更加清晰,完全可以写一个PVPlayer.cpp,将PVPlayer.cpp相关代码写在这个PVPlayer.cpp中,尽管代码不是特别多。
  3) 是该看一下PVPlayer的初始化过程了:
    看PVPlayer的构造函数,最主要的就就创建了Playerdriver对象( mPlayerDriver = new PlayerDriver(this);),所以,PlayerDriver的构造才是核心。

3. PlayerDriver的构造:

在 PlayerDriver 的构造过程中,最主要做了 3 件事情:

 

   1) Semaphore (信号量)的创建:

    mSyncSem = new OsclSemaphore();

   mSyncSem->Create();

   2)load libopencorehw.so:

mLibHandle = ::dlopen(MIO_LIBRARY_NAME, RTLD_NOW); //MIO_LIBRARY_NAME = "libopencorehw.so";

3) 开始 player thread

createThreadEtc(PlayerDriver::startPlayerThread , this, "PV player");

 

4. PlayerDriver::playerThread的实现:

startPlayerThread会call playerThread,playerThread是真正创建PV thread的函数。

int PlayerDriver::playerThread()
{
    int error;

    LOGV("InitializeForThread");
    if (!InitializeForThread())
    {
        LOGV("InitializeForThread fail");
        mPlayer = NULL;
        mSyncSem->Signal();
        return -1;
    }

    LOGV("OMX_MasterInit");
    OMX_MasterInit();

    LOGV("OsclScheduler::Init");
    OsclScheduler::Init("AndroidPVWrapper");

    LOGV("CreatePlayer");
    OSCL_TRY(error, mPlayer = PVPlayerFactory::CreatePlayer(this, this, this));
    if (error) {
        // Just crash the first time someone tries to use it for now?
        mPlayer = NULL;
        mSyncSem->Signal();
        return -1;
    }

    LOGV("AddToScheduler");
    AddToScheduler();
    LOGV("PendForExec");
    PendForExec();

    LOGV("OsclActiveScheduler::Current");
    OsclExecScheduler *sched = OsclExecScheduler::Current();
    LOGV("StartScheduler");
    error = OsclErrNone;
    OSCL_TRY(error, sched->StartScheduler(mSyncSem));
    OSCL_FIRST_CATCH_ANY(error,
                         // Some AO did a leave, log it
                         LOGE("Player Engine AO did a leave, error=%d", error)
                        );

    LOGV("DeletePlayer");
    PVPlayerFactory::DeletePlayer(mPlayer);

    delete mDownloadContextData;
    mDownloadContextData = NULL;

    delete mDataSource;
    mDataSource = NULL;
    delete mAudioSink;
    PVMediaOutputNodeFactory::DeleteMediaOutputNode(mAudioNode);
    delete mAudioOutputMIO;
    delete mVideoSink;
    if (mVideoNode) {
        PVMediaOutputNodeFactory::DeleteMediaOutputNode(mVideoNode);
        delete mVideoOutputMIO;
    }

    mSyncStatus = OK;
    mSyncSem->Signal();
    // note that we only signal mSyncSem. Deleting it is handled
    // in enqueueCommand(). This is done because waiting for an
    // already-deleted OsclSemaphore doesn't work (it blocks),
    // and it's entirely possible for this thread to exit before
    // enqueueCommand() gets around to waiting for the semaphore.

    // do some of destructor's work here
    // goodbye cruel world
    delete this;

    //Moved after the delete this, as Oscl cleanup should be done in the end.
    //delete this was cleaning up OsclSemaphore objects, eventually causing a crash
    OsclScheduler::Cleanup();
    LOGV("OsclScheduler::Cleanup");

    OMX_MasterDeinit();
    UninitializeForThread();
    return 0;
}

简析:
1).OMX_MasterInit 的调用,这正好是OMX协议定义中规定的要调用的第一个函数。
2).OsclScheduler::Init("AndroidPVWrapper");
3).OSCL_TRY(error, mPlayer = PVPlayerFactory::CreatePlayer(this, this, this)); 通过Factory模式来创建Player.
   在pv_player_factory.cpp中,有:
OSCL_EXPORT_REF PVPlayerInterface *PVPlayerFactory::CreatePlayer(PVCommandStatusObserver* aCmdStatusObserver,
        PVErrorEventObserver *aErrorEventObserver,
        PVInformationalEventObserver *aInfoEventObserver,
        bool aHwAccelerated)
{
    return PVPlayerEngine::New(aCmdStatusObserver, aErrorEventObserver, aInfoEventObserver, aHwAccelerated);  // 会创建PVPlayerEngine的实例。
}
4).AddToScheduler();
5).PendForExec();
6).OSCL_TRY(error, sched->StartScheduler(mSyncSem));
   StartScheduler的实现:
       (1)  call BlockingLoopL
               A. call CallRunExec(pvactive);  // PVActiveBase *pvactive, 真正的对象是PlayerDriver实例。
                      a.     call pvactive->Run() // 调用PlayerDriver的run.
   分析:在PlayerDriver的run函数中,根据command的命令来执行相应的handle函数。

7).可以看到,与OSCl层的调用,创建Engine的代码,具体,请读者自己看源码来理解吧。

 

5.  PVPlayerDriver中command的定义与理解:

<!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } -->

 

对PVPlayerDriver 的各种操作使用各种命令来完成,这些命令在playerdriver.h 中进行的定义。

enum player_command_type {

PLAYER_QUIT = 1,

PLAYER_SETUP = 2,

PLAYER_SET_DATA_SOURCE = 3,

PLAYER_SET_VIDEO_SURFACE = 4,

PLAYER_SET_AUDIO_SINK = 5,

PLAYER_INIT = 6,

PLAYER_PREPARE = 7,

PLAYER_START = 8,

PLAYER_STOP = 9,

PLAYER_PAUSE = 10,

PLAYER_RESET = 11,

PLAYER_SET_LOOP = 12,

PLAYER_SEEK = 13,

PLAYER_GET_POSITION = 14,

PLAYER_GET_DURATION = 15,

PLAYER_GET_STATUS = 16,

PLAYER_REMOVE_DATA_SOURCE = 17,

PLAYER_CANCEL_ALL_COMMANDS = 18,

PLAYER_CHECK_LIVE_STREAMING = 19

};

 

这些命令一般实现的是PVPlayerInterface 各个接口的简单封装,例如对于较为简单的暂停播放这个操作,整个系统执行的过程如下所示:

(1) .在PVPlayer 中的pause 函数(在playerdriver.cpp 文件中)

status_t PVPlayer::pause()

{

LOGV("pause");

return mPlayerDriver->enqueueCommand(new PlayerPause(0,0));

}

这时调用其成员mPlayerDriver (PlayerDriver 类型)的函数,将一个PlayerPause 命令加入了命令序列,具体的各种命令功能在playerdriver.h 文件中。

(2) .PlayerDriver 类的enqueueCommand 将间接调用各个以handle 为开头的函数,对于PlayerPause 命令,调用的函数是handlePause

void PlayerDriver::handlePause(PlayerPause* ec)

{

LOGV("call pause");

mPlayer->Pause(0);

FinishSyncCommand(ec);

}

这里的mPlayer 是一个PVPlayerInterface 类型的指针,使用这个指针调用到了OpenCore 的 Player Engine 中的PVPlayerEngine 类。

在这个播放器适配器的实现中,一个主要的工作是将Android 框架中定义的媒体的输出(包括Audio 的输出和Video 的输出)转换成,OpenCore 的 Player Engine 需要的形式。在这里两个重要的类是android_surface_output.cpp 实现的AndroidSurfaceOutput ,android_audio_output.cpp 实现的AndroidAudioOutput 。

对于Video 输出的设置过程,在类PlayerDriver 中定义了3 个成员:

PVPlayerDataSink *mVideoSink;

PVMFNodeInterface *mVideoNode;

PvmiMIOControl *mVideoOutputMIO;

这里的mVideoSink 的类型为PVPlayerDataSink ,这是Player Engine 中定义的类接口,mVideoNode 的类型为PVMFNodeInterface ,在pvmi/pvmf/include 的pvmf_node_interface.h 中定义,这是所有的PVMF 的NODE 都需要继承的统一接口,mVideoOutputMIO 的类型为PvmiMIOControl 也在pvmi/pvmf/include 中定义,这是媒图输出控制的接口类。

(1) .在PVPlayer 的setVideoSurface 用以设置一个Video 输出的界面,这里使用的参数的类型是ISurface 指针:

status_t PVPlayer::setVideoSurface(const sp<ISurface>& surface)

{

LOGV("setVideoSurface(%p)", surface.get());

mSurface = surface;

return OK;

}

setVideoSurface 函数设置的是PVPlayer 中的一个成员mSurface ,真正设置Video 输出的界面的功能在run_set_video_surface() 函数中实现:

void PVPlayer::run_set_video_surface(status_t s, void *cookie)

{

LOGV("run_set_video_surface s=%d", s);

if (s == NO_ERROR) {

PVPlayer *p = (PVPlayer*)cookie;

if (p->mSurface == NULL) {

run_set_audio_output(s, cookie);

} else {

p->mPlayerDriver->enqueueCommand(new PlayerSetVideoSurface(p->mSurface, run_set_audio_output, cookie));

}

}

}

这时使用的命令是PlayerSetVideoSurface ,最终将调用到PlayerDriver 中的handleSetVideoSurface 函数。

(2) .handleSetVideoSurface 函数的实现如下所示:

void PlayerDriver::handleSetVideoSurface(PlayerSetVideoSurface* ec)

{

int error = 0;

mVideoOutputMIO = new AndroidSurfaceOutput(ec->surface());

mVideoNode = PVMediaOutputNodeFactory::CreateMediaOutputNode(mVideoOutputMIO);

mVideoSink = new PVPlayerDataSinkPVMFNode;

 

((PVPlayerDataSinkPVMFNode *)mVideoSink)->SetDataSinkNode(mVideoNode);

((PVPlayerDataSinkPVMFNode *)mVideoSink)->SetDataSinkFormatType(PVMF_YUV420);

 

OSCL_TRY(error, mPlayer->AddDataSink(*mVideoSink, ec));

OSCL_FIRST_CATCH_ANY(error, commandFailed(ec));

}

在这里首先建立的创建成员mVideoOutputMIO (类型为PvmiMIOControl ),这时建立的类是类AndroidSurfaceOutput ,这个类继承了PvmiMIOControl ,所以可以作为PvmiMIOControl 使用。然后调用PVMediaOutputNodeFactory::CreateMediaOutputNode 建立了PVMFNodeInterface 类型的mVideoNode 。随后创建PVPlayerDataSinkPVMFNode 类型的mVideoSink ,PVPlayerDataSinkPVMFNode 本身继承了PVPlayerDataSink ,因此可以作为PVPlayerDataSink 使用。调用SetDataSinkNode 函数将mVideoNode 设置为mVideoSink 的数据输出节点。

 

 

结语:再次说一下,opencore将在2.3版本中彻底消失,但是OMX还会在stagefright中继续使用。不过对于上层应用来说,不用管这些,因为接口没有变化。

 

 

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片 基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正 立即下载

相关推荐

一文吃透 BMS:动力电池与储能共用的电池管控全架构详解

BMS作为电池系统的核心控制器,其技术深度和系统复杂性不容小觑。动力电池与储能系统虽然应用场景不同,但在核心架构上共享大量基础技术。成功的BMS设计需要在精度、可靠性、成本、功耗之间找到最佳平衡点。未来,随着电池技术的进步和智能化需求的提升,BMS将向着更高集成度、更强智能化、更优经济性的方向发展。无论是汽车工程师还是储能系统设计师,深入理解BMS的全栈架构,掌握其核心技术原理,都将是应对未来能源存储挑战的关键能力。核心要点回顾BMS采用分层分布式架构,硬件是基础,算法是灵魂。

小帽子的博客 339

嵌入式系统多媒体框架分析

嵌入式系统多媒体框架分析 1 Android系统的多媒体框架 Google正式对外发布的Android版本,在Android2.3版本之前,使用的是Opencore多媒体框架,Android2.3版本及之后的Android系统,以Stagefright多媒体框架取代Opencore多媒体框架。Opencore多媒体框架结构过于庞大复杂,Stagefright多媒体框架提高了多媒体框架的灵活性和

麦麦麦先森的小世界 3507

Llama模型结构拆解:为什么MLP模块要这样设计?从参数配置到计算流程全解析

本文深入解析了Llama模型MLP模块的设计精髓。通过拆解其三线性层结构、门控机制与SwiGLU激活函数,揭示了并行计算如何提升效率,并详细阐述了intermediate_size参数配置背后的经验权衡与计算考量,帮助读者透彻理解这一核心组件的设计逻辑与工程实现。

mac99的博客 529

使用OpenCore引导黑苹果

笔者在17年写过一篇黑苹果安装教程:[黑苹果系统安装通用教程(Clover引导)](https://blog.csdn.net/unreliable_narrator/article/details/64438619),不过该文章用的是基于Clover引导的MacOs系统。目前随着黑苹果的另一款引导工具OpenCore不断成熟,使用OC是大势所趋。众多黑苹果驱动的作者已经停止对Clover的兼容支持,改向Opencore的兼容。OpenCore是类似于Clover的UEFI的引导器,OpenCore提供了详

XBlithe的博客 2万+

基于深度学习卷积神经网络的医学图像乳腺癌分类

一、项目背景与意义乳腺癌是女性最常见的恶性肿瘤之一,其早期发现和治疗对于提高患者的生存率和生活质量至关重要。然而,乳腺癌的诊断通常依赖于医生的经验和主观判断,这不仅耗时而且可能存在误差。近年来,深度学习技术特别是卷积神经网络(CNN)在图像处理领域取得了显著进展,为乳腺癌的自动分类提供了新的解决方案。本项目旨在利用深度学习卷积神经网络构建一套高效、准确的医学图像乳腺癌分类系统,辅助医生进行乳腺癌的早期诊断和治疗。二、技术实现。

2301_79810943的博客 976

chipseeker Y叔

这一次讲解非常重要的peak注释,注释在ChIPseeker里只需要用到一个函数annotatePeak,它可以满足大家各方面的需求。 输入 当然需要我们上次讲到的BED文件,ChIPseeker自带了5个BED文件,用getSampleFiles()可以拿到文件的全路径,它返回的是个named list,我这里取第4个文件来演示。annotatePeak的输入也可以是GRanges对象,你如果用R做peak calling的话,直接就可以衔接上ChIPseeker了。 require(ChIPseeke

生信小博士的博客 1589

Hackintosh(黑苹果)bigsur (opencore引导)超级详细教程

镜像文件(zip解压缩后为raw格式的镜像) 阿里云盘链接: efi文件 阿里云盘链接:链接 其他型号的笔记本可以去这里找找有没有和自己型号一样或者类似的,或者去github,百度等搜索,主要是看电脑配置。如果配置和下面一样就可以直接使用我提供的efi文件了 我的配置 型号:Asus X411UN CPU:i5-8250U (Kaby Lake) 声卡:Conexant CX8050 显卡:Intel UHD 620 独立显卡:NVIDIA MX130 已屏蔽 硬盘:128固态+1T机械 如何查看

teruha的博客 2万+

基于Matlab的深度学习OFDM系统信号检测

在接收端,我们首先去除循环前缀,然后对接收到的信号进行FFT变换和QAM解调。在通信系统中,正交频分复用(Orthogonal Frequency Division Multiplexing,OFDM)是一种常用的调制技术,它可以将高速数据流分成若干个低速子载波进行传输,提高了信道利用率和抗干扰性能。接下来,我们使用训练好的神经网络对QAM调制后的数据进行检测,得到估计的FFT变换结果。深度学习方法可以通过大量的训练数据来学习信号的特征,并具有一定的适应能力,在某些情况下可能能够获得更好的检测性能。

2301_79325657的博客 296

【免费下载】 OpenCore 配置工具使用教程

OpenCore 配置工具(OC-tool)是一个用于生成和编辑 OpenCore 配置文件(config.plist)以及 EFI 文件夹的工具。该工具旨在简化 OpenCore 引导加载程序的配置过程,特别适用于黑苹果用户。OC-tool 提供了图形界面和命令行选项,使用户能够轻松地管理 OpenCore 版本和配置文件。 ## 项目快速启动 ### 安装与运行 1. **克隆项目仓库*...

gitblog_00403的博客 2583

第77步 时间序列建模实战:多因素预测 vol-2(以决策树回归为例)

第77步 时间序列建模实战:多因素预测 vol-2(以决策树回归为例)

Jet4505的博客 1008

Docker Desktop 从 C 盘迁移到 D 盘的正确方法

本文介绍了三种将Docker数据目录从C盘迁移到D盘的方案。方案1针对WSL2用户,通过导出/导入虚拟磁盘实现迁移;方案2采用软链接方式,适合所有Docker模式;方案3则建议重装Docker到D盘。其中WSL2迁移方案(方案1)最为稳定可靠,推荐使用。文章详细说明了各方案的操作步骤及注意事项,并提供了迁移后常见问题的解决方法,帮助用户彻底解决Docker占用C盘空间的问题。

sg_knight的专栏 2178

Android多媒体框架OpenCore(PacketVideo)介绍之三:Player和Auther

<br />                                                          第五部分 OpenCore Player介绍 <br />5.1 Player的组成 <br />      OpenCore的Player的编译文件是pvplayer/Android.mk,将生成动态库文件 libopencoreplayer.so。这个库包含了两方面的内容:一方是Player的engine(引擎),一方面是为Android构件的Player,这实际上是一个适配器

雨辰专栏 1168

(持续更新中!)详解【计算机类&面试真题】军队文职考试 ——第二期(真题+解析)| 网络协议的三个核心要素;交互式系统中的非剥夺策略;中断和陷入的区别;可变分区管理中的硬件机制;数据库系统的优点

本篇博客将讨论军队文职面试(计算机类)的几个关键问题。我们将介绍网络协议的核心要素(帮助你理解网络通信的基本原理)、交互式系统中的非剥夺策略(解释为何这是一个优秀的策略以及其对用户体验、系统稳定性和可预测性的影响)、中断和陷入的区别(从引起原因、处理机制、权限级别和应用等方面进行阐述)、可变分区管理的硬件机制以及数据库系统与文件系统的优点比较。通过阅读本文,您将深入了解这些话题,为面试准备和实际应用提供有价值的知识。

追光者♂:记录、分享、总结、提升,现象级专栏《Python从入门到人工智能》作者,无惧黑暗,坚信曙光 1707

Android多媒体框架初步分析

Android多媒体框架初步分析<br />邹德文<br /> Android 系统整体架构:<br />我们先看一下多媒体框架在整个Android系统所处的位置<br /><br /> <br /> <br />从框架图可以看出Media Framework处于Libraries这一层,这层的Library不是用Java实现,一般是C/C++实现,它们通过Java的JNI方式调用。<br /> <br /> <br />多媒体架构:<br />基于第三方PacketVideo 公司的OpenCORE pl

gracioushe的专栏 424

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Android多媒体之Media Player

 多媒体,现代手机不可或缺的一部分,它包含了音视频播放器、照相机、录音机、摄像机、FM、移动电视、Gallery等等。在中国10年以前手机中的添加这些功能模块或许是想都不敢想的,但是10年之中各种专用功能的手机的出现,如带FM的手机、音乐手机、摄像手机、带移动电视的手机,让我们越来越觉得一部强大的手机理所当然应该包含这些功能。没错,我们可以细数一下,好像这些功能许多山寨机都已经支持,托山寨机的福,

arm10504的专栏 1386

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Android音视频API - MediaCodec/MediaMuxer/MediaStore/MediaController等

AudioTrack播放音频PCM。[Android] 混音器AudioMixer。 MediaPlayer/MediaRecorder, AudioTrack/AudioRecorder, MediaCodec。 -- 使用MediaCodec和MediaMuxer的过程中遇到的问题,总结下需要注意主要有以下几点: 1.MediaCodec是Android4.1新增API,MediaMuxe...

ShareUs的专栏 2191

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Android 本地视频播放

android 本地视频播放

qq_26711419的博客 281

如何用OpenCore配置工具5步完成黑苹果安装:终极可视化指南

还在为复杂的黑苹果配置而烦恼吗?手动编辑OpenCore配置文件不仅耗时费力,还容易出错。今天我要介绍的**OpenCore配置工具**正是为了解决这个痛点而生——它是一款专为黑苹果用户设计的可视化配置软件,让复杂的引导配置变得像填表格一样简单。 [![OpenCore配置工具应用界面](https://raw.gitcode.com/gh_mirrors/op/OpenCore-Configu

gitblog_00759的博客 184

黑苹果使用opencore添加驱动

黑苹果注入驱动程序

学习记录 8484

Android多媒体框架及解决方案:VLC,ffmpeg,GStreamer,SDL等

-- Android 多媒体解决方案:Android MediaPlayer;FFmpeg;Google ExoPlayer;Vitamio;VLC。 1.Android MediaPlayer 是 Android 内置的播放器,支持格式很有限:3gp mp4,且不支持流媒体。 2.FFmpeg 是一套功能强大的跨平台多媒体解决方案,需要用NDK编译,支持海量格式、流媒体。 3.Googl...

ShareUs的专栏 2306

android webrtc 视频流源码获取帧图像VideoFrame转bitmap 作为图像识别

由于需要使用opencv等项目识别webrtc中的画面 需要对webrtc的摄像头进行采集 该方法在EglRenderer implements VideoSink 类的onFrame中增加saveImgBitmap(frame)方法来获取图像具体代码如下 // VideoSink interface. @Override public void onFrame(VideoFrame frame){ //将org.webrtc.VideoFrame转bitmap并保存 saveImgBitm.

b275518834的专栏 3370
上一篇: Linux系统中exec函数蔟的使用:execl,execv,execle,execve,execlp,execvp
下一篇: Linux系统中IO多路复用select函数的使用,及其在Android系统中的运用
liranke
博客等级 码龄20年 4939粉丝 594原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值