美文网首页
编码图片动画为视频

编码图片动画为视频

作者: 阿斯顿英朗 | 来源:发表于2020-07-16 16:48 被阅读0次

    已解决:问题出在我Java层的buffer和NDK的buffer是共享的,然后我为了加快速度,主线程截图和NDK的编码过程多线程进行,导致主线程获取出下一帧时污染了部分正在转换的数据。。。

    解决过程:仙人掌D 的文章给了我解决方法,就是用ffplay打开编码前的rgb帧和yuv帧的数据,后来又对比了Java层的bmp数据,才突然意识到Java层的bmp没问题,为何传到NDK后,rgb就有问题了呢,最神奇的是rgb帧和yuv帧的问题还不一样,应该是污染程度不一样,yuv污染更严重,我猜应该是因为sws转换过程时间较长,上面一部分没污染,下面一部分污染了

    另外编译FFmpeg和x264也使用了仙人掌D 的文章,特此感谢!


    // 1、查找编码器

        AVCodec *avcodec = avcodec_find_encoder(AV_CODEC_ID_H264);

        if (avcodec == NULL){

            return JNI_FALSE;

        }

        //1、获取编码器上下文

        AVCodecContext *avcodec_context = avcodec_alloc_context3(avcodec);

        //2、设置编解码器上下文参数

        avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P;

        avcodec_context->width = width;

        avcodec_context->height = width;

        // 设置帧率25fps

        avcodec_context->time_base = (AVRational){1, 25};

        avcodec_context->framerate = (AVRational){25, 1};

        // 设置码率

        avcodec_context->bit_rate = 4096000;

        // 设置GOP

        avcodec_context->gop_size = 250;

        avcodec_context->max_b_frames = 0; //必须是0,否则Mac&iOS无法播放

        if (avcodec->id == AV_CODEC_ID_H264) {

            av_opt_set(avcodec_context->priv_data, "preset", "slow", 0);

            av_opt_set(avcodec_context->priv_data, "tune", "film", 0);

        }

        int openRet = avcodec_open2(avcodec_context, avcodec, NULL);

        if (openRet < 0) {

            return JNI_FALSE;

        }

    // 2、内存空间填充

    AVFrame *rgbFrame = av_frame_alloc();

    rgbFrame->format =AV_PIX_FMT_BGRA; //AV_PIX_FMT_RGBA,AV_PIX_FMT_ABGR,AV_PIX_FMT_ARGB

    rgbFrame->width = width;

    rgbFrame->height = width;

    AVFrame *yuvFrame = av_frame_alloc();

    yuvFrame->format = avcodec_context->pix_fmt;

    yuvFrame->width = width;

    yuvFrame->height = width;

    av_frame_get_buffer(rgbFrame, 32);

    av_frame_get_buffer(yuvFrame, 32);

    SwsContext *img_convert_ctx = sws_getContext(avcodec_context->width,

                                                avcodec_context->height,

                                                static_cast(rgbFrame->format),

                                                avcodec_context->width,

                                                avcodec_context->height,

                                                avcodec_context->pix_fmt,

                                                SWS_BICUBIC, NULL, NULL, NULL);

    循环处理图片序列:

    while ... {

    int *bmpIntData = env->GetIntArrayElements(bmpIntArray, &isCopy);

            const uint8_t *bmpData = (const uint8_t *)bmpIntData;

            av_image_fill_arrays(rgbFrame->data,

                                rgbFrame->linesize,

                                bmpData,

                                static_cast(rgbFrame->format),

                                rgbFrame->width,

                                rgbFrame->height,

                                1);

            int ret = sws_scale(img_convert_ctx, rgbFrame->data, rgbFrame->linesize, 0, avcodec_context->height, yuvFrame->data, yuvFrame->linesize);

            if (0 > ret) {

    status =JNI_FALSE;

    break;

            }

            yuvFrame->pts = i;

            encodeFrame(avcodec_context, yuvFrame, av_packet, h264Output);

    }

    //其他一些收尾工作

    //mergeH264AndAacToMp4 封装成mp4

    下面是视频里图片淡入淡出过程的截图,有奇怪的半块灰色蒙层

    相关文章

      网友评论

          本文标题:编码图片动画为视频

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