2017-04-26 95 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); 
}