首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Android :如何替换AAsset以处理来自外部存储的文件以进行FFmpeg解码

Android :如何替换AAsset以处理来自外部存储的文件以进行FFmpeg解码
EN

Stack Overflow用户
提问于 2020-01-07 22:59:20
回答 1查看 475关注 0票数 2

我正在使用双簧管的RhytmGame例子作为一个指南来实现双簧管和mp3解码使用FFmpeg到我的应用程序。由于我对NDK相当陌生,而且还是C++初学者,所以我仍然很难理解我遇到的一些基本概念。我的问题是:上面提到的示例仅使用Android的AssetManager的本机实现处理来自资产文件夹的文件。由于我希望访问外部存储的文件,我必须改变这一点,但我不清楚如何做到这一点。

这就是我陷入困境的地方:我有一个FFmpegExtractor类,它在FFmpeg's avio.h中调用此方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 * Allocate and initialize an AVIOContext for buffered I/O. It must be later
 * freed with avio_context_free().
 *
 * @param buffer Memory block for input/output operations via AVIOContext.
 *        The buffer must be allocated with av_malloc() and friends.
 *        It may be freed and replaced with a new buffer by libavformat.
 *        AVIOContext.buffer holds the buffer currently in use,
 *        which must be later freed with av_free().
 * @param buffer_size The buffer size is very important for performance.
 *        For protocols with fixed blocksize it should be set to this blocksize.
 *        For others a typical size is a cache page, e.g. 4kb.
 * @param write_flag Set to 1 if the buffer should be writable, 0 otherwise.
 * @param opaque An opaque pointer to user-specific data.
 * @param read_packet  A function for refilling the buffer, may be NULL.
 *                     For stream protocols, must never return 0 but rather
 *                     a proper AVERROR code.
 * @param write_packet A function for writing the buffer contents, may be NULL.
 *        The function may not change the input buffers content.
 * @param seek A function for seeking to specified byte position, may be NULL.
 *
 * @return Allocated AVIOContext or NULL on failure.
 */
AVIOContext *avio_alloc_context(
                  unsigned char *buffer,
                  int buffer_size,
                  int write_flag,
                  void *opaque,
                  int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),
                  int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),
                  int64_t (*seek)(void *opaque, int64_t offset, int whence));

在这里打电话:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool FFMpegExtractor::createAVIOContext(AAsset *asset, uint8_t *buffer, uint32_t bufferSize,
                                        AVIOContext **avioContext) {

    constexpr int isBufferWriteable = 0;

    *avioContext = avio_alloc_context(
            buffer, // internal buffer for FFmpeg to use
            bufferSize, // For optimal decoding speed this should be the protocol block size
            isBufferWriteable,
            asset, // Will be passed to our callback functions as a (void *)
            read, // Read callback function
            nullptr, // Write callback function (not used)
            seek); // Seek callback function

    if (*avioContext == nullptr){
        LOGE("Failed to create AVIO context");
        return false;
    } else {
        return true;
    }
}

我希望替换assetreadseek参数,这样我就可以使用存储中的文件而不是AAsset对象。

这是上面传递的read回调:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int read(void *opaque, uint8_t *buf, int buf_size) {

    auto asset = (AAsset *) opaque;
    int bytesRead = AAsset_read(asset, buf, (size_t)buf_size);
    return bytesRead;
}

这是seek回调:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int64_t seek(void *opaque, int64_t offset, int whence){

    auto asset = (AAsset*)opaque;

    // See https://www.ffmpeg.org/doxygen/3.0/avio_8h.html#a427ff2a881637b47ee7d7f9e368be63f
    if (whence == AVSEEK_SIZE) return AAsset_getLength(asset);
    if (AAsset_seek(asset, offset, whence) == -1){
        return -1;
    } else {
        return 0;
    }
}

我尝试过用文件替换AAsset,但这当然做不到。我知道如何打开和读取文件,但我不清楚这是否是这里所期望的,以及如何将AAsset中的方法转换为返回存储中文件所需值的操作。谁能给我指明正确的方向?

编辑:下面是我对@BrianChen的有益评论的回复中提到的代码块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bool FFMpegExtractor::openAVFormatContext(AVFormatContext *avFormatContext) {

    int result = avformat_open_input(&avFormatContext,
                                     "", /* URL is left empty because we're providing our own I/O */
                                     nullptr /* AVInputFormat *fmt */,
                                     nullptr /* AVDictionary **options */
    );

不幸的是,avformat_open_input()生成一个

Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x20 in tid 23767, pid 23513

EN

回答 1

Stack Overflow用户

发布于 2020-01-09 23:15:01

这与使用AAsset是一样的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// wrapper class for file stream 
class  MediaSource {
public:
    MediaSource() {
    }
    ~MediaSource() {
        source.close();
    }
    void open(const string& filePath) {
        source.open(filePath, ios::in | ios::binary);
    }
    int read(uint8_t *buffer, int buf_size) {
        // read data to buffer
        source.read((char *)buffer, buf_size)
        // return how many bytes were read
        return source.gcount();
    }
    int64_t seek(int64_t offset, int whence) {
        if (whence == AVSEEK_SIZE) {
            // FFmpeg needs file size.
            int oldPos = source.tellg();
            source.seekg(0,ios::end);
            int64_t length = source.tellg();
            // seek to old pos
            source.seekg(oldPos);
            return length;
        } else if (whence == SEEK_SET) {
            // set pos to offset
            source.seekg(offset);
        } else if (whence == SEEK_CUR) {
            // add offset to pos
            source.seekg(offset, ios::cur);
        } else {
            // do not support other flags, return -1
            return -1;
        }
        // return current pos
        return source.tellg();
    }
private:
    ifstream source;
};

// If FFmpeg needs to read the file, it will call this function.
// We need to fill the buffer with file's data.
int read(void *opaque, uint8_t *buffer, int buf_size) {
    MediaSource *source = (MediaSource *)opaque;
    return source->read(buffer, buf_size);
}

// If FFmpeg needs to seek in the file, it will call this function.
// We need to change the read pos.
int64_t seek(void *opaque, int64_t offset, int whence) {
    MediaSource *source = (MediaSource *)opaque;
    return source->seek(offset, whence);
}

// add MediaSource to class FFMpegExtractor
class FFMpegExtractor {
private:
    // add this line to declare of class FFMpegExtractor
    MediaSource* mSource;
};

FFMpegExtractor::FFMpegExtractor() {
    // add this line in constructor, new a instance
    mSource = new MediaSource;
}

FFMpegExtractor::~FFMpegExtractor() {
    // add this line in destructor, release instance
    delete mSource;
}

bool FFMpegExtractor::createAVIOContext(const string& filePath, uint8_t *buffer, uint32_t bufferSize,
                                        AVIOContext **avioContext) {

    mSource.open(filePath);
    constexpr int isBufferWriteable = 0;

    *avioContext = avio_alloc_context(
            buffer, // internal buffer for FFmpeg to use
            bufferSize, // For optimal decoding speed this should be the protocol block size
            isBufferWriteable,
            mSource, // Will be passed to our callback functions as a (void *)
            read, // Read callback function
            nullptr, // Write callback function (not used)
            seek); // Seek callback function

    if (*avioContext == nullptr){
        LOGE("Failed to create AVIO context");
        return false;
    } else {
        return true;
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59640862

复制
相关文章
C++ 中的随机标头系列1
开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
鲸落c
2022/11/28
1.4K0
C++ 中的随机标头系列1
设置和获取HTTP标头
%Net.HttpRequest的以下每个属性都包含具有相应名称的HTTP标头的值。如果不设置这些属性,则会自动计算它们:
用户7741497
2022/06/09
2.5K0
通过 HTTP 标头的 XSS
在某些情况下,在应用程序的一个 HTTP 标头中传递的信息未正确清理,并在请求页面的某处或另一端输出,从而导致 XSS 情况。
Khan安全团队
2022/03/09
2.1K0
通过主机标头的 XSS
在 IE 中处理重定向时有一个有趣的错误,它可以将任意字符插入到 Host 标头中。假设您有以下 http 响应:
Khan安全团队
2022/01/11
1.6K0
常见的HTTP标头介绍
在网络爬虫的实践过程中会遇到诸多挑战,被屏蔽是最令人头疼的一个。幸好,有许多技术可以帮助您免受IP屏蔽带来的影响,这其中,HTTP标头(HTTP Headers)的使用和优化是最有效的方法之一,但它往往也是最被大家低估的方法之一。
用户7850017
2022/05/07
1.1K0
常见的HTTP标头介绍
跨国摄像头通过国标协议注册EasyGBS后摄像头SIP协议被更改怎么办?
我们遇到过很多用户有跨国视频播放的情况,一般我们会推荐用户采用非国标协议来进行对接,但如果项目有需求,也会碰到跨国需要使用国标协议传输的情况。
TSINGSEE青犀视频
2021/12/15
6880
Log4Shell HTTP 标头注入
此模块需要 Metasploit:https://metasploit.com/download
Khan安全团队
2022/01/14
1.1K0
「HTTP标头」都给你整理好了
HTTP 1.1 的标头主要分为四种,通用标头、实体标头、请求标头、响应标头,现在我们来对这几种标头进行介绍
Java3y
2020/02/19
5.8K0
「HTTP标头」都给你整理好了
wordpress更改固定链接后404
wordpress的固定链接对于博客的seo优化是非常重要的。因为有些默认设置并不怎么友好,所以我们可以自定义设置自己的想要的固定链接,比如自定义连接结构为:/%post_id%.html。但是往往我们更改之后会出现404页面,这是网站的伪静态出了问题。 下面是在不同环境下的不同解决方法。
SweetHunter
2020/05/10
2.1K0
芯片后仿及SDF反标
启用SDF反标。在file.sdf中指定的最小值、类型或最大值中的一种,在实例instance_name上进行反标。
数字芯片社区
2021/12/02
5.5K0
芯片后仿及SDF反标
废掉腾讯云后:美亚柏科 9830 万中标
2021年9月30日,珠海市公安局(科信支队)珠海公安大数据智能化建设采购项目公开招标公告发布,预算 103398915.2 元。 中标结果 2021年10月22日中标(成交)结果公告发布,腾讯云计算(北京)有限责任公司 100,127,866.00 元中标。 综合评分法汇总表: 废标公告 2021年12月25日废标公告发布,本项目因故根据《中华人民共和国政府采购法》第36条规定,做废标处理。 《中华人民共和国政府采购法》第36条规定: 在招标采购中,出现下列情形之一的,应予废标: (一)符合专业条件的
云头条
2022/07/13
8170
废掉腾讯云后:美亚柏科 9830 万中标
使用结构化的标头字段改善HTTP
原文 / https://www.fastly.com/blog/improve-http-structured-headers
LiveVideoStack
2020/08/04
6660
CentOS挂载NAS存储后权限的更改
最后我们为了安全,再次将'根限制'勾选,这样做的意义是:就算你用nfs3挂载的文件系统,那么依然无法修改属主属组,更为安全,如下图:
染指流年
2023/03/13
4.1K0
CentOS挂载NAS存储后权限的更改
服务器未能识别 HTTP 标头 SOAPAction 的值
SOAPAction HTTP request header被用来标识SOAP HTTP请求的目的地,其值是个URI地址。SOAP发送并不限制格式、URI特征或其必须可解析,那么在这种情况下,发送一个HTTP SOAP请求时,其HTTP客户端必须使用/指明SOAPAction HTTP request header。 SOAPAction header的内容可以被用在服务端,诸如:防火墙适当的过滤基于HTTP的SOAP请求消息等场景。SOAPAction header的值为空串("")表示SOAP消息的目
张善友
2018/01/19
3.1K0
ThinkPHP5.1中URL重写.htaccess更改后无效的解决方法
昨天是打算更换项目框架的,决定了这个 ThinkPHP5,我使用的是 5.1 版本 开发中一直不喜欢 URL 中有这个index.php,这个时候就要使用.htaccess 来进行 URL 重写,之前有文章大概介绍了一下简单配置.htaccess 就可以实现的几个功能以及.htaccess 文件使用手册,框架都会通过 URL 重写隐藏应用的入口文件index.php,ThinkPHP 框架和 Laravel 框架的入口文件路径一样,都是在public下面 本地开发使用的是 Apache 环境,所以按照官方文
沈唁
2018/05/24
10.9K1
安卓开发_浅谈Fragment之ListFragment
ListFragment,即Fragment的一个子类,当我们用的一个Fragment只需要一个listview视图的时候使用 该类有几个特点: 1、ListFragment 本身具只有一个ListView视图,返回的也是一个只有ListView的布局对象 2、ListFragment 不需要指定布局,本身固定,只有一个ListView视图 3、给ListFragment中的ListView加载数据或者绑定适配器都只能出现onCreateView(),因为onCreateView方法之后,ListView对
听着music睡
2018/05/18
2.1K0
浪潮云被废标后、东华软件 5724 万中标:河北省“智慧交管”项目(第五包)
2021年11月23日,河北省公安厅高速公路交通警察总队发布《“智慧交管”项目开发统一应用门户、应用平台;公安网、视频专网云平台、地理信息平台等部分》招标公告。 项目概况:项目建设内容主要包括完善高速公路前端智能感知系统,建设高速交警总队智慧交管大脑、统一应用门户、智慧交管应用平台、一体化指挥调度平台、智能化统一管理平台,升级高速交警总队公安交通集成指挥平台,升级改造高速交警总队、11个支队、22个大队指挥中心配套设施,同时租赁移动警务服务、链路和机柜。 招标范围:(第五包)开发统一应用门户、应用平台;公安
云头条
2022/05/17
5690
浪潮云被废标后、东华软件 5724 万中标:河北省“智慧交管”项目(第五包)
树莓派更改Wi-Fi后不重启
//配置Wi-Fi 配置你的Wi-Fi信息 sudo vi /etc/wpa_supplicant/wpa_supplicant.conf
用户2458545
2022/09/07
4510
Android开发之ListFragment结合LoaderManager加载数据
之前实现过Android开发之ContentProvider结合LoaderManager加载数据,现在来实现用ListFragment加载 先看main.xml
提莫队长
2019/03/01
6750
Android开发之ListFragment结合LoaderManager加载数据
点击加载更多

相似问题

在Nsis中查找Powershell路径

17

如何使用常量更改R中的文件路径?

22

如何使用NSIS EnVar插件编辑路径?

222

我们是否有任何常量来获取NSIS中的当前用户路径

17

如何使用openFileOutput()指定文件路径?

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文