2012-12-12 10 views
7

Supose Ich habe eine ganze Videodatei im Speicher und möchte mit libav die ganzen Bilder dekodieren. Wie soll ich das machen? Der Punkt ist, dass ich es lesen kann direkt aus einer Datei mit avformat_open_input() -Funktion, aber ich muss es tun, aus einer Datei, die im Speicher gespeichert ist.Eine Videodatei mit libav aus dem Speicher dekodieren

Meine AVIOContext Implementierung:

class AVIOMemContext 
{ 

public: 

    AVIOMemContext(char* videoData, const int videoLen) 
    { 
     // Output buffer 
     bufferSize = 32768; 
     buffer = static_cast<char*>(av_malloc(bufferSize)); 

     // Internal buffer 
     pos = 0; 
     this->videoData = videoData; 
     this->videoLen = videoLen; 

     ctx_ = avio_alloc_context((unsigned char*) buffer, bufferSize, AVIO_FLAG_READ, this, &AVIOMemContext::read, &AVIOMemContext::write, &AVIOMemContext::seek); 
    } 

    ~AVIOMemContext() 
    { 
     av_free(videoData); 
    } 

    static int read(void *opaque, unsigned char *buf, int buf_size) 
    { 
     AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque); 

     // Read from pos to pos + buf_size 
     if (This->pos + buf_size > This->videoLen) 
     { 
      int len = This->videoLen - This->pos; 
      memcpy(buf, This->videoData + This->pos, len); 
      return len; 
     } 
     else 
     { 
      memcpy(buf, This->videoData + This->pos, buf_size); 
      return buf_size; 
     } 
    } 

    static int write(void *opaque, unsigned char *buf, int buf_size) 
    { 
     /* 
     AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque); 
     return fwrite(buf, 1, buf_size, This->f_); 
     */ 

     return 0; 
    } 

    static int64_t seek(void *opaque, int64_t offset, int whence) 
    { 
     AVIOMemContext* This = static_cast<AVIOMemContext*>(opaque); 

     if (offset + whence > This->videoLen) 
     { 
      This->pos = This->videoLen; 

      return -1; 
     } 
     else 
     { 
      This->pos = offset + whence; 

      return 0; 
     } 
    } 

    AVIOContext *get_avio() 
    { 
     return ctx_; 
    } 

private: 

    // Output buffer 
    int bufferSize; 
    char* buffer; 

    // Internal buffer 
    int pos; 
    char* videoData; 
    int videoLen; 

    AVIOContext* ctx_; 

}; 

Mein aktueller Code:

[...] 

av_register_all(); 
avcodec_register_all(); 

AVFormatContext* context; 
AVCodec* pCodec; 
AVPacket packet; 
AVCodecContext* pCodecCtx; 
int video_stream_index; 
int res; 
int got_picture; 

// Init variables and objects 
context = avformat_alloc_context(); 

AVIOMemContext priv_ctx(videoData, videoLen); 
context->pb = priv_ctx.get_avio(); 

res = avformat_find_stream_info(context, NULL); 

if (res < 0) 
{ 
    // Error 
    avformat_free_context(context); 

    return 0; 
} 

// Obtain the video stream of the total set of streams 
for (unsigned int k = 0; k < context->nb_streams; ++k) 
{ 
    if (context->streams[k]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
     video_stream_index = k; 
    context->streams[k]->codec->time_base.den = 90000; 
} 

pCodecCtx = context->streams[video_stream_index]->codec; 
pCodec = avcodec_find_decoder(pCodecCtx->codec_id); 

avcodec_open(pCodecCtx, pCodec); 

//allocate video frame 
AVFrame *pFrame = avcodec_alloc_frame(); 

unsigned int nFrame = 0; 

while (av_read_frame(context, &packet) >= 0) 

[...] 

Vielen Dank im Voraus,

Dídac Pérez

Antwort

3

Sie können Ihre eigenen AVIOContext erstellen. Sie müssen ::avio_alloc_context anrufen und dann auf AVFormatContext::pb setzen. Für Details, siehe meine Antwort auf How can libavformat be used without using other libav libraries?

+0

Vielen Dank für Ihre Hilfe, ich werde es jetzt versuchen. –

+0

Ich habe meinen eigenen AVIOContext erstellt, aber die App stürzt ab in avformat_find_stream_info() –

Verwandte Themen