FFMpeg:未指定的像素格式

时间:2019-06-05 18:39:44

标签: c++ ffmpeg

我正在尝试用C ++编写代码以解码来自内存的视频流。我知道我必须使用AVIOContext并实现读取和查找功能才能使其正常工作。但是就我而言,我仍然得到

  

未指定像素格式

尝试读取框架时出错。

#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <fstream>

using namespace std;

extern "C"
{
#include <libavformat\avformat.h>
#include <libavcodec\avcodec.h>
#include <libswscale/swscale.h>
}

static int ReadFunc(void* opaque, uint8_t* buf, int buf_size) {
    auto& stream = *reinterpret_cast<istream*>(opaque);
    auto bufPtr = reinterpret_cast<char*>(buf);
    stream.read(bufPtr, buf_size);
    auto readBytes = stream.gcount();
    return readBytes;
}

static int64_t SeekFunc(void *opaque, int64_t offset, int whence) {
    auto& me = *reinterpret_cast<istream*>(opaque);

    switch (whence) {
    case SEEK_SET:
        me.seekg(offset, me.beg);
        break;
    case SEEK_CUR:
        offset += me.tellg();
        me.seekg(offset, me.beg);
        break;
    case SEEK_END:
        me.seekg(offset, me.end);
        break;
    case (AVSEEK_SIZE):
        int64_t currentOffset = me.tellg();

        me.seekg(0, ios::end);
        long size = me.tellg();

        me.seekg(currentOffset, me.beg);

        return size; 
    }

    auto pos = me.tellg();
    return pos;
}

int main()
{
    int err;

    av_register_all();

    ifstream stream("c:\\temp\\file.mp4", ios::binary);

    const int iBufSize = 32768;

    const shared_ptr<unsigned char> buffer(reinterpret_cast<unsigned char*>(av_malloc(iBufSize)), &av_free);

    auto bufferPtr = buffer.get();

    const shared_ptr<AVIOContext> avioContext(avio_alloc_context(pBuffer, iBufSize, 0, reinterpret_cast<void*>(static_cast<istream*>(&stream)), &ReadFunc, nullptr, &SeekFunc), &av_free);
    const auto avFormat = shared_ptr<AVFormatContext>(avformat_alloc_context(), &avformat_free_context);

    auto avFormatPtr = avFormat.get();

    avFormat->pb = avioContext.get();

/* This code simply crashes, not sure if it's needed
    stream.read(reinterpret_cast<char*>(bufferPtr), iBufSize);
    ULONG bytesRead = stream.gcount();
    stream.seekg(0, stream.beg);

    AVProbeData probeData;
    probeData.buf = bufferPtr;
    probeData.buf_size = bytesRead;
    probeData.filename = "";

    avFormatPtr->iformat = av_probe_input_format(&probeData, 1); */

    avFormat->flags = AVFMT_FLAG_CUSTOM_IO;

    avformat_open_input(&avFormatPtr, "", nullptr, nullptr);

    err = avformat_find_stream_info(avFormatPtr, NULL);
    if (err < 0) {
        fprintf(stderr, "ffmpeg: Unable to find stream info\n");
        return -1;
    }

    int vid_stream;
    for (vid_stream = 0; vid_stream < avFormatPtr->nb_streams; ++vid_stream)
    {
        if (avFormatPtr->streams[vid_stream]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            break;
        }
    }
    if (vid_stream == avFormatPtr->nb_streams)
    {
        fprintf(stderr, "ffmpeg: Unable to find video stream\n");
        return -1;
    }

    AVCodecContext* codec_context = avFormatPtr->streams[vid_stream]->codec;
    AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
    err = avcodec_open2(codec_context, codec, NULL);
    if (err < 0) {
        fprintf(stderr, "ffmpeg: Unable to open codec\n");
        return -1;
    }

    // init frame
    AVFrame* frame = av_frame_alloc();
    frame = av_frame_alloc();
    if (!frame)
    {
        av_log(NULL, AV_LOG_ERROR, "Cannot init frame\n");
    }

    //init packet
    AVPacket *pkt = NULL;
    pkt = av_packet_alloc();
    av_init_packet(pkt);
    if (!pkt)
    {
        av_log(NULL, AV_LOG_ERROR, "Cannot init packet\n");
    }

    /*avFormatPtr->max_analyze_duration = INT64_MAX;
    avFormatPtr->probesize = INT64_MAX;*/

    while (av_read_frame(avFormatPtr, pkt) >= 0) {
        if (pkt->stream_index == vid_stream) {
            // Video stream packet
            int frame_finished;
            avcodec_decode_video2(codec_context, frame, &frame_finished, pkt);

            if (frame_finished)
            {
                // FRAME DECODED
            }
        }

        av_free_packet(pkt);
    }

    // Free the YUV frame
    av_free(frame);

    // Close the codec
    avcodec_close(codec_context);

    // Close the video file
    avformat_close_input(&avFormatPtr);

    return 0;
}

类似的question已经存在。解决的办法是添加我执行的搜索功能。我是否正确实现了Seek函数?它的行为很奇怪,有时要求的偏移量是-1。我的代码和此问题的代码示例之间的主要区别是,在我的情况下使用的是istream而不是FILE对象,但是我是C ++的新手,所以好像我缺少一些东西。

0 个答案:

没有答案