예제 #1
0
bool VideoDecoderCUDAPrivate::createCUVIDParser()
{
    cudaVideoCodec cudaCodec = mapCodecFromFFmpeg(codec_ctx->codec_id);
    if (cudaCodec == -1) {
        qWarning("CUVID does not support the codec");
        available = false;
        return false;
    }
    if (parser) {
        cuvidDestroyVideoParser(parser);
        parser = 0;
    }
    //lavfilter check level C
    CUVIDPARSERPARAMS parser_params;
    memset(&parser_params, 0, sizeof(CUVIDPARSERPARAMS));
    parser_params.CodecType = cudaCodec;
    /*!
     * CUVIDPICPARAMS.CurrPicIdx <= kMaxDecodeSurfaces.
     * CUVIDPARSERDISPINFO.picture_index <= kMaxDecodeSurfaces
     * HandlePictureDecode must check whether CUVIDPICPARAMS.CurrPicIdx is in use
     * HandlePictureDisplay must mark CUVIDPARSERDISPINFO.picture_index is in use
     * If a frame is unmapped, mark the index not in use
     *
     */
    parser_params.ulMaxNumDecodeSurfaces = nb_dec_surface;
    //parser_params.ulMaxDisplayDelay = 4; //?
    parser_params.pUserData = this;
    parser_params.pfnSequenceCallback = VideoDecoderCUDAPrivate::HandleVideoSequence;
    parser_params.pfnDecodePicture = VideoDecoderCUDAPrivate::HandlePictureDecode;
    parser_params.pfnDisplayPicture = VideoDecoderCUDAPrivate::HandlePictureDisplay;
    parser_params.ulErrorThreshold = 0;//!wait for key frame
    //parser_params.pExtVideoInfo

    qDebug("~~~~~~~~~~~~~~~~extradata: %p %d", codec_ctx->extradata, codec_ctx->extradata_size);
    /*!
     * NOTE: DO NOT call h264_extradata_to_annexb here if use av_bitstream_filter_filter
     * because av_bitstream_filter_filter will call h264_extradata_to_annexb and marks H264BSFContext has parsed
     * h264_extradata_to_annexb will not mark it
     * LAVFilter's
     */
#if FILTER_ANNEXB_CUVID
    memset(&extra_parser_info, 0, sizeof(CUVIDEOFORMATEX));
    // nalu
    // TODO: check mpeg, avc1, ccv1? (lavf)
    if (codec_ctx->extradata && codec_ctx->extradata_size >= 6) {
        int ret = h264_extradata_to_annexb(codec_ctx, FF_INPUT_BUFFER_PADDING_SIZE);
        if (ret >= 0) {
            qDebug("%s @%d ret %d, size %d", __FUNCTION__, __LINE__, ret, codec_ctx->extradata_size);
            memcpy(extra_parser_info.raw_seqhdr_data, codec_ctx->extradata, codec_ctx->extradata_size);
            extra_parser_info.format.seqhdr_data_length = codec_ctx->extradata_size;
        }
    }
    parser_params.pExtVideoInfo = &extra_parser_info;
#endif
    checkCudaErrors(cuvidCreateVideoParser(&parser, &parser_params));
    //lavfilter: cuStreamCreate
    force_sequence_update = true;
    //DecodeSequenceData()
    return true;
}
예제 #2
0
static int h264_mp4toannexb_init(AVBSFContext *ctx)
{
    H264BSFContext *s = ctx->priv_data;
    int extra_size = ctx->par_in->extradata_size;
    int ret;

    /* retrieve sps and pps NAL units from extradata */
    if (!extra_size                                               ||
        (extra_size >= 3 && AV_RB24(ctx->par_in->extradata) == 1) ||
        (extra_size >= 4 && AV_RB32(ctx->par_in->extradata) == 1)) {
        av_log(ctx, AV_LOG_VERBOSE,
               "The input looks like it is Annex B already\n");
    } else if (extra_size >= 6) {
        ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE);
        if (ret < 0)
            return ret;

        s->length_size      = ret;
        s->first_idr        = 1;
        s->extradata_parsed = 1;
    } else {
        av_log(ctx, AV_LOG_ERROR, "Invalid extradata size: %d\n", extra_size);
        return AVERROR_INVALIDDATA;
    }

    return 0;
}
예제 #3
0
static int h264_mp4toannexb_init(AVBSFContext *ctx)
{
    H264BSFContext *s = ctx->priv_data;
    int ret;

    /* retrieve sps and pps NAL units from extradata */
    if (ctx->par_in->extradata_size >= 6) {
        ret = h264_extradata_to_annexb(ctx, AV_INPUT_BUFFER_PADDING_SIZE);
        if (ret < 0)
            return ret;

        s->length_size      = ret;
        s->new_idr          = 1;
        s->idr_sps_seen     = 0;
        s->idr_pps_seen     = 0;
        s->extradata_parsed = 1;
    }

    return 0;
}
static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
                                   AVCodecContext *avctx, const char *args,
                                   uint8_t **poutbuf, int *poutbuf_size,
                                   const uint8_t *buf, int buf_size,
                                   int keyframe)
{
    H264BSFContext *ctx = bsfc->priv_data;
    int i;
    uint8_t unit_type;
    int32_t nal_size;
    uint32_t cumul_size    = 0;
    const uint8_t *buf_end = buf + buf_size;
    int ret = 0;

    /* nothing to filter */
    if (!avctx->extradata || avctx->extradata_size < 6) {
        *poutbuf      = (uint8_t *)buf;
        *poutbuf_size = buf_size;
        return 0;
    }

    /* retrieve sps and pps NAL units from extradata */
    if (!ctx->extradata_parsed) {
        if (args && strstr(args, "private_spspps_buf"))
            ctx->private_spspps = 1;

        ret = h264_extradata_to_annexb(ctx, avctx, AV_INPUT_BUFFER_PADDING_SIZE);
        if (ret < 0)
            return ret;
        ctx->length_size      = ret;
        ctx->new_idr          = 1;
        ctx->idr_sps_seen     = 0;
        ctx->idr_pps_seen     = 0;
        ctx->extradata_parsed = 1;
    }

    *poutbuf_size = 0;
    *poutbuf      = NULL;
    do {
        ret= AVERROR(EINVAL);
        if (buf + ctx->length_size > buf_end)
            goto fail;

        for (nal_size = 0, i = 0; i<ctx->length_size; i++)
            nal_size = (nal_size << 8) | buf[i];

        buf      += ctx->length_size;
        unit_type = *buf & 0x1f;

        if (buf + nal_size > buf_end || nal_size < 0)
            goto fail;

        if (unit_type == 7)
            ctx->idr_sps_seen = ctx->new_idr = 1;
        else if (unit_type == 8) {
            ctx->idr_pps_seen = ctx->new_idr = 1;
            /* if SPS has not been seen yet, prepend the AVCC one to PPS */
            if (!ctx->idr_sps_seen) {
                if (ctx->sps_offset == -1)
                    av_log(avctx, AV_LOG_WARNING, "SPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                else {
                    if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
                                         ctx->spspps_buf + ctx->sps_offset,
                                         ctx->pps_offset != -1 ? ctx->pps_offset : ctx->spspps_size - ctx->sps_offset,
                                         buf, nal_size)) < 0)
                        goto fail;
                    ctx->idr_sps_seen = 1;
                    goto next_nal;
                }
            }
        }

        /* if this is a new IDR picture following an IDR picture, reset the idr flag.
         * Just check first_mb_in_slice to be 0 as this is the simplest solution.
         * This could be checking idr_pic_id instead, but would complexify the parsing. */
        if (!ctx->new_idr && unit_type == 5 && (buf[1] & 0x80))
            ctx->new_idr = 1;

        /* prepend only to the first type 5 NAL unit of an IDR picture, if no sps/pps are already present */
        if (ctx->new_idr && unit_type == 5 && !ctx->idr_sps_seen && !ctx->idr_pps_seen) {
            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
                               ctx->spspps_buf, ctx->spspps_size,
                               buf, nal_size)) < 0)
                goto fail;
            ctx->new_idr = 0;
        /* if only SPS has been seen, also insert PPS */
        } else if (ctx->new_idr && unit_type == 5 && ctx->idr_sps_seen && !ctx->idr_pps_seen) {
            if (ctx->pps_offset == -1) {
                av_log(avctx, AV_LOG_WARNING, "PPS not present in the stream, nor in AVCC, stream may be unreadable\n");
                if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
                                     NULL, 0, buf, nal_size)) < 0)
                    goto fail;
            } else if ((ret = alloc_and_copy(poutbuf, poutbuf_size,
                                        ctx->spspps_buf + ctx->pps_offset, ctx->spspps_size - ctx->pps_offset,
                                        buf, nal_size)) < 0)
                goto fail;
        } else {
            if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
                               NULL, 0, buf, nal_size)) < 0)
                goto fail;
            if (!ctx->new_idr && unit_type == 1) {
                ctx->new_idr = 1;
                ctx->idr_sps_seen = 0;
                ctx->idr_pps_seen = 0;
            }
        }

next_nal:
        buf        += nal_size;
        cumul_size += nal_size + ctx->length_size;
    } while (cumul_size < buf_size);

    return 1;

fail:
    av_freep(poutbuf);
    *poutbuf_size = 0;
    return ret;
}
예제 #5
0
static int h264_mp4toannexb_filter(AVBitStreamFilterContext *bsfc,
                                   AVCodecContext *avctx, const char *args,
                                   uint8_t **poutbuf, int *poutbuf_size,
                                   const uint8_t *buf, int buf_size,
                                   int keyframe)
{
  H264BSFContext *ctx = bsfc->priv_data;
  int i;
  uint8_t unit_type;
  int32_t nal_size;
  uint32_t cumul_size    = 0;
  const uint8_t *buf_end = buf + buf_size;
  int ret = 0;

  /* nothing to filter */
  if (!avctx->extradata || avctx->extradata_size < 6) {
    *poutbuf      = (uint8_t *)buf;
    *poutbuf_size = buf_size;
    return 0;
  }

  /* retrieve sps and pps NAL units from extradata */
  if (!ctx->extradata_parsed) {
    ret = h264_extradata_to_annexb(avctx, FF_INPUT_BUFFER_PADDING_SIZE);
    if (ret < 0)
      return ret;
    ctx->length_size      = ret;
    ctx->first_idr        = 1;
    ctx->extradata_parsed = 1;
  }

  *poutbuf_size = 0;
  *poutbuf      = NULL;
  do {
    ret= AVERROR(EINVAL);
    if (buf + ctx->length_size > buf_end)
      goto fail;

    for (nal_size = 0, i = 0; i<ctx->length_size; i++)
      nal_size = (nal_size << 8) | buf[i];

    buf      += ctx->length_size;
    unit_type = *buf & 0x1f;

    if (buf + nal_size > buf_end || nal_size < 0)
      goto fail;

    /* prepend only to the first type 5 NAL unit of an IDR picture */
    if (ctx->first_idr && unit_type == 5) {
      if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
                              avctx->extradata, avctx->extradata_size,
                              buf, nal_size)) < 0)
        goto fail;
      ctx->first_idr = 0;
    } else {
      if ((ret=alloc_and_copy(poutbuf, poutbuf_size,
                              NULL, 0, buf, nal_size)) < 0)
        goto fail;
      if (!ctx->first_idr && unit_type == 1)
        ctx->first_idr = 1;
    }

    buf        += nal_size;
    cumul_size += nal_size + ctx->length_size;
  } while (cumul_size < buf_size);

  return 1;

  fail:
  av_freep(poutbuf);
  *poutbuf_size = 0;
  return ret;
}