FFmpeg解码裸H264数据

项目地址源码https://github.com/liluojun/PlayVideo

      之前弄了下Android硬解H264https://blog.csdn.net/hjt505694246/article/details/105046233,但是硬解多少还是受到硬件影响所有再折腾下ffmpeg软解。

关于ffmpeg解码的文章很多我也是业余接触下并且我对C语言也是个初学者,有不足的地方还请见谅。

先上代码

先初始化解码器

int FFmpegEncode::creatFFmpeg(AVCodecID id) {
    avcodec_register_all();
    mAVCodec = avcodec_find_decoder(id);
    if (mAVCodec == NULL) {
        printf("mAVCodec==NULL\n");
        return -1;
    }

    mAVCodecContext = avcodec_alloc_context3(mAVCodec);
    if (mAVCodecContext == NULL) {
        printf("mAVCodecContext==NULL\n");
        return -1;
    }
    if (avcodec_open2(mAVCodecContext, mAVCodec, NULL) < 0) {
        printf("avcodec_open2 error\n");
        return -1;
    }
    mAVFrame = av_frame_alloc();
    if (!mAVFrame) {
        printf("av_frame_alloc error\n");
        return -1;
    }
    mAVPacket = av_packet_alloc();
    if (!mAVPacket) {
        printf("av_packet_alloc error\n");
        return -1;
    }
    av_init_packet(mAVPacket);
    return 0;
}
设置解码参数:宽高、帧率、数据类型
int FFmpegEncode::initAVCodecContext(int width, int heigth, int fps, AVPixelFormat pixFmt) {
    if (mAVCodecContext == NULL) {
        printf("initAVCodecContext NULL\n");
        return -1;
    }
    if (width <= 0 || heigth <= 0 || fps <= 10) {
        printf("initAVCodecContext Parameters of the abnormal\n");
        return -1;
    }
    mAVCodecContext->width = width;
    mAVCodecContext->height = heigth;
    mAVCodecContext->frame_bits = fps;
    mAVCodecContext->pix_fmt = pixFmt;
    return 0;
}
喂数据解码:framedata是源数据,*outputY,*outputU,*outputV是解码后的yuv三个分量数据,pixfmt数据类型。
这里我有个拷贝的动作,据说有零拷贝的方式,有木有大佬知道的可以指点一下。
int FFmpegEncode::encodeFFmpeg(uint8_t *framedata, int framelen,//input
                               uint8_t *outputY, uint8_t *outputU, uint8_t *outputV, int *width,
                               int *height,
                               AVPixelFormat pixfmt) {
    if (mAVPacket == NULL) {
        printf("encodeFFmpeg NULL\n");
        return -1;
    }
    mAVPacket->data = framedata;
    mAVPacket->size = framelen;
    while (mAVPacket->size > 0) {
        if (avcodec_send_packet(mAVCodecContext, mAVPacket)) {
            printf("%s %d avcodec_send_packet fail\n", __func__, __LINE__);
            return -2;
        }
        if (avcodec_receive_frame(mAVCodecContext, mAVFrame)) {
            printf("%s %d avcodec_receive_frame fail\n", __func__, __LINE__);
            return -3;
        }

        switch (mAVCodecContext->pix_fmt) {
            case AV_PIX_FMT_YUV420P: {
                memcpy(outputY, mAVFrame->data[0], *width * *height);
                memcpy(outputU, mAVFrame->data[1], *width * *height / 4);
                memcpy(outputV, mAVFrame->data[2], *width * *height / 4);

                width = &(mAVCodecContext->width);
                height = &(mAVCodecContext->height);
                pixfmt = mAVCodecContext->pix_fmt;
                break;
            }
            case AV_PIX_FMT_NV21: {

                memcpy(outputY, mAVFrame->data[0], *width * *height);
                memcpy(outputU, mAVFrame->data[1], *width * *height / 4);
                memcpy(outputV, mAVFrame->data[2], *width * *height / 4);
                width = &(mAVCodecContext->width);
                height = &(mAVCodecContext->height);
                pixfmt = mAVCodecContext->pix_fmt;
                break;
            }
            default: {
                printf("mAVCodecContext->pix_fmt Failure to identify\n");
                return -4;
            }
        }

        return 0;
    }
}
释放解码器资源
void
FFmpegEncode::unEncode() {
    avcodec_close(mAVCodecContext);
    av_free(mAVCodecContext);
    av_frame_free(&mAVFrame);
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值