2017-04-26 70 views
0

我正在尝试将FFmpeg实现到SFML中,因此我有更广泛的音频文件可供读取,但打开m4a文件时出现错误[mov,mp4,m4a,3gp,3g2,mj2 @ #] moov atom not found。现在只有当我使用自定义IOContext来读取文件而不是从URL打开它时才会发生这种情况。 This page这里说我不应该使用流打开m4a文件,但是被视为流的IOContext?因为我无法将其作为URL以SFML的工作方式打开。使用自定义IOContext时未找到ffmpeg库m4a moov atom

// Explanation of InputStream class 
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 
}; 

// Used for IOContext 
int read(void* opaque, uint8_t* buf, int buf_size) { 
    sf::InputStream* stream = (sf::InputStream*)opaque; 
    return (int)stream->read(buf, buf_size); 
} 
// Used for IOContext 
int64_t seek(void* opaque, int64_t offset, int whence) { 
    sf::InputStream* stream = (sf::InputStream*)opaque; 
    switch (whence) { 
    case SEEK_SET: 
     break; 
    case SEEK_CUR: 
     offset += stream->tell(); 
     break; 
    case SEEK_END: 
     offset = stream->getSize() - offset; 
    } 
    return (int64_t)stream->seek(offset); 
} 

bool open(sf::InputStream& stream) { 
    AVFormatContext* m_formatContext = NULL; 
    AVIOContext* m_ioContext = NULL; 
    uint8_t* m_ioContextBuffer = NULL; 
    size_t m_ioContextBufferSize = 0; 

    av_register_all(); 
    avformat_network_init(); 
    m_formatContext = avformat_alloc_context(); 

    m_ioContextBuffer = (uint8_t*)av_malloc(m_ioContextBufferSize); 
    if (!m_ioContextBuffer) { 
     close(); 
     return false; 
    } 
    m_ioContext = avio_alloc_context(
     m_ioContextBuffer, m_ioContextBufferSize, 
     0, &stream, &::read, NULL, &::seek 
    ); 
    if (!m_ioContext) { 
     close(); 
     return false; 
    } 
    m_formatContext = avformat_alloc_context(); 
    m_formatContext->pb = m_ioContext; 

    if (avformat_open_input(&m_formatContext, NULL, NULL, NULL) != 0) { 
     // FAILS HERE 
     close(); 
     return false; 
    } 

    //... 

    return true; 
} 

回答

0

事实证明,只有一个问题,它与我的寻求功能。显然ffmpeg有另一个可用的选项AVSEEK_SIZE。这是实现。在此之后它工作。

int64_t seek(void* opaque, int64_t offset, int whence) { 
    sf::InputStream* stream = (sf::InputStream*)opaque; 
    switch (whence) { 
    case SEEK_SET: 
     break; 
    case SEEK_CUR: 
     offset += stream->tell(); 
     break; 
    case SEEK_END: 
     offset = stream->getSize() - offset; 
     break; 
    case AVSEEK_SIZE: 
     return (int64_t)stream->getSize(); 
    } 
    return (int64_t)stream->seek(offset); 
}