gpt4 book ai didi

安卓 NDK : How to replace AAsset to work with files from external Storage for FFmpeg decoding

转载 作者:行者123 更新时间:2023-12-02 10:37:29 25 4
gpt4 key购买 nike

我正在使用 Oboe's RhytmGame example作为使用 FFmpeg 实现双簧管和 mp3 解码的指南进入我的应用程序。由于我对 NDK 和 C++ 初学者还很陌生,我仍然在为遇到的一些基本概念而苦恼。
我的问题:上面提到的示例只处理 Assets 文件夹中的文件,使用 Android 的 AssetManager 的 native 实现。
由于我希望访问外部存储上的文件,因此我必须更改此设置,但我不清楚如何执行此操作。

这是我卡住的地方:
我有一个 FFmpegExtractorFFmpeg's avio.h 中调用此方法的类:

 * 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));

调用在这里:
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;
}
}

我正在寻找替换 asset , readseek参数,以便我可以使用存储中的文件而不是 AAsset 对象。

这是 read上面传递的回调:
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打回来:
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;
}
}

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

编辑:因为它不适合这里是我在回复@BrianChen 的有用评论中提到的代码块:
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

最佳答案

这与使用 AAsset 相同。

// 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;
}
}

关于安卓 NDK : How to replace AAsset to work with files from external Storage for FFmpeg decoding,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59640862/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com