为了从视频流中读取字节,应该使用哪个c函数?

时间:2019-08-17 21:00:45

标签: parsing video decode h.264 libav

我尝试使用Libav解码.mkv文件中的h.264流,因此我必须使用一个函数来读取容器中stream [i]存在的地址。我想将整个流存储在某个位置的缓冲区中,以应用例如parse_nal_units函数(我无法使用av_read_frame进行读取,因为我不知道一个帧有多长)。据我所知,fread仅从文件读取,并且我没有文件,只有地址。解决此问题的最佳方法是什么?

而不是//将输入文件中的一帧读取到一个临时包中。     while(!(ret = av_read_frame(ifmt_ctx,&input_packet))&&(ret> = 0))我应该在缓冲区中读取整个流,然后通过h264解析器对其进行解析。

这里有一些代码

for (i = 0; i < ifmt_ctx->nb_streams; i++)
{
    AVStream *in_stream = ifmt_ctx->streams[i], *out_stream ;
    AVCodec *pCodec = NULL, *oCodec = NULL;
    AVCodecParameters *inpar;
    AVCodecContext *avctx= NULL, *oavctx= NULL;
    AVPacket input_packet;
    AVFrame *iframe = NULL, *oframe = NULL;
    AVCodecParserContext *parser = NULL;
    const uint8_t *poutbuf;
    int poutbuf_size;
    int *finished;

    //------------------------------Decode----------------------------------

    //Find decoder pCodec
    if (!(pCodec =avcodec_find_decoder(in_stream->codecpar->codec_id))){
    fprintf(stderr, "Could not find input codec\n");
    //avformat_close_input(input_format_context);
    return AVERROR_EXIT;
    }

    // Allocate a new decoding context.
    avctx = avcodec_alloc_context3(pCodec);
    if (!avctx) {
    fprintf(stderr, "Could not allocate a decoding context\n");
    avformat_close_input(ifmt_ctx);
    return AVERROR(ENOMEM);
    }

    // Initialize the stream parameters with demuxer information.
    ret = avcodec_parameters_to_context(avctx, ifmt_ctx->streams[i]->codecpar);
    if (ret < 0) {
    avformat_close_input(ifmt_ctx);
    avcodec_free_context(&avctx);
    return ret;
    }
    //Open the decoder
    if ((ret = avcodec_open2(avctx, pCodec, NULL)) < 0) {
    fprintf(stderr, "Could not open input codec (error '%s')\n",
            get_error_text(ret));
    avcodec_free_context(&avctx);
    avformat_close_input(ifmt_ctx);
    return ret;
    }

    //Prepare data

    if (!(iframe = av_frame_alloc())) {
        fprintf(stderr, "Could not allocate input frame\n");
        return AVERROR(ENOMEM);
    }

    parser = av_parser_init(pCodec->id);

    if (!parser) {
    fprintf(stderr, "parser not found\n");
    exit(1);
    }
    //----------------------Decode & Encode---------------------------

    switch (pCodec->type) {

    case AVMEDIA_TYPE_VIDEO:

     //------------------Set encoder format and context-----------------------

        // Find the encoder to be used by its ID.
        if (!(oCodec = avcodec_find_encoder(AV_CODEC_ID_MPEG4))) {
        fprintf(stderr, "Could not find an AV_CODEC_ID_MPEG4 encoder.\n");
        goto end;
        }

        init_packet(&input_packet);
    // Read one frame from the input file into a temporary packet.
    while(!(ret = av_read_frame(ifmt_ctx, &input_packet))&&(ret>=0)){

        ret = av_parser_parse2(parser, avctx, &poutbuf, &poutbuf_size, (&input_packet)->data, (&input_packet)->size,
                            AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
        if (ret < 0) {
            fprintf(stderr, "Error while parsing\n");
            exit(1);
            }

         if ((ret = avcodec_send_packet(avctx, &input_packet)) < 0) {
            fprintf(stderr, "Could not send packet for decoding (error '%s')\n",get_error_text(ret));
            return ret;
        }

        ret = avcodec_receive_frame(avctx, iframe);
        if (ret == AVERROR(EAGAIN)) {
            goto read_another_frame;
            /* If the end of the input file is reached, stop decoding. */
        } else if (ret == AVERROR_EOF) {
            break;
        } else if (ret < 0) {
            fprintf(stderr, "Could not decode frame (error '%s')\n",get_error_text(ret));
            break;
        }
        // Default case: encode data
         else {

        }

        read_another_frame:
            av_packet_unref(&input_packet);

    }
    if (ret == AVERROR_EOF)
            *finished = 1;
        else {
            fprintf(stderr, "Could not read frame (error '%s')\n",
                    get_error_text(ret));
            return ret;
                }
        break;

谢谢

0 个答案:

没有答案