美文网首页
FFmpeg解码裸H264数据

FFmpeg解码裸H264数据

作者: 璃云曦 | 来源:发表于2020-03-23 14:48 被阅读0次

    项目地址源码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);

    }

    相关文章

      网友评论

          本文标题:FFmpeg解码裸H264数据

          本文链接:https://www.haomeiwen.com/subject/pgjwyhtx.html