繁体   English   中英

ffmpeg avformat_open_input与自定义流对象

[英]ffmpeg avformat_open_input with custom stream object

我目前正在尝试使用ffmpeg的库编写针对SFML的自定义SoundFileReader 我唯一可以与avcodec和avformat一起使用的是InputStream类,它是SFML的一部分。 我查看了avformat_open_inputAVIOContext并学习了如何将自定义流与缓冲区一起使用,但是如何创建可与自定义读取,查找和lseek函数一起使用的AVIOContext

class InputStream {
    int64_t getSize()
    int64_t read(void* data, int64_t size);
    int64_t seek(int64_t position);
    int64_t tell(); // Gets the stream position
};

您需要编写一组回调函数,然后将指针传递给这些回调,并将不透明的参数传递给avio_alloc_context 请注意,这些回调不得抛出。

/// <summary>
/// Reads up to buffer_capacity_bytes_count bytes into supplied buffer.
/// Basically should work like ::read C method.
/// </summary>
/// <param name="opaque">
/// Opaque pointer to reader instance. Passing nullptr is not allowed.
/// </param>
/// <param name="p_buffer">
/// Pointer to data buffer. Passing nullptr is not allowed.
/// </param>
/// <param name="buffer_capacity_bytes_count">
/// Size of the buffer pointed to by p_buffer, in bytes.
/// Passing value less than or equal to 0 is not allowed.
/// </param>
/// <returns>
/// Non negative values containing amount of bytes actually read. 0 if EOF has been reached.
/// -1 if an error occurred.
/// </returns>
static auto
Read(void * const opaque, uint8_t * const p_buffer, int const buffer_capacity_bytes_count) noexcept
{
    int result{-1};
    if(opaque && p_buffer && (0 <= buffer_capacity_bytes_count))
    {
        auto & stream{*reinterpret_cast< InputStream * >(opaque)};
        try
        {
            auto const read_result{stream.read(p_buffer, buffer_capacity_bytes_count)};
            if((0 <= read_result) && (read_result <= buffer_capacity_bytes_count))
            {
                result = read_result;
            }
        }
        catch(...)
        {
            // print error or something
        }
    }
    return(result);
}

/// <summary>
/// Changes file pointer position or retrieves file size.
/// Basically should work like ::lseek and ::fstat C methods.
/// </summary>
/// <param name="opaque">
/// Opaque pointer to reader instance. Passing nullptr is not allowed.
/// </param>
/// <param name="pos">
/// Target offset. When retrieving file size this should be 0.
/// </param>
/// <param name="whence">
/// Flag indicating operation. Valid values are SEEK_SET, SEEK_CUR, SEEK_END (as in C library),
/// AVSEEK_SIZE and optional AVSEEK_FORCE bit.
/// </param>
/// <returns>
/// Non-negative values containing offset of the file pointer or file size in bytes.
/// Negative values if an error occurred.
/// </returns>
static auto
Seek(void * const opaque, int64_t const pos, int const whence) noexcept
{
    int64_t result{AVERROR(EBADF)};
    if(opaque)
    {
        auto & stream{*reinterpret_cast< InputStream * >(opaque)};
        try
        {
            auto const action{whence & (SEEK_SET | SEEK_CUR | SEEK_END | AVSEEK_SIZE)};
            auto const forced{0 != (whence & AVSEEK_FORCE)}; // can be ignored
            switch(action)
            {
                case SEEK_SET:
                case SEEK_CUR:
                case SEEK_END:
                {
                    // TODO perform seek...
                    break;
                }
                case AVSEEK_SIZE:
                {
                    result = stream.getSize();
                    break;
                }
            }
        }
        catch(...)
        {
            // print error or something
        }
    }
    return(result);
}

...

InputStream stream;
auto const opaque{reinterpret_cast< void * >(::std::addressof(stream))};
auto p_io_context
{
    ::avio_alloc_context
    (
        static_cast< unsigned char * >(p_buffer) // ownership is not transferred
    ,   buffer_size
    ,   0 // 0 if openning for reading, 1 if openning for writing
    ,   opaque
    ,   &Read
    ,   nullptr // write callback function, not used if we open for reading
    ,   &Seek
    )
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM