编码图片动画为视频

2020-07-16  本文已影响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

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

上一篇 下一篇

猜你喜欢

热点阅读