已解決:?jiǎn)栴}出在我Java層的buffer和NDK的buffer是共享的上陕,然后我為了加快速度,主線程截圖和NDK的編碼過(guò)程多線程進(jìn)行范删,導(dǎo)致主線程獲取出下一幀時(shí)污染了部分正在轉(zhuǎn)換的數(shù)據(jù)。。宙橱。
解決過(guò)程:仙人掌D 的文章給了我解決方法,就是用ffplay打開編碼前的rgb幀和yuv幀的數(shù)據(jù)烦磁,后來(lái)又對(duì)比了Java層的bmp數(shù)據(jù)养匈,才突然意識(shí)到Java層的bmp沒問題,為何傳到NDK后都伪,rgb就有問題了呢呕乎,最神奇的是rgb幀和yuv幀的問題還不一樣,應(yīng)該是污染程度不一樣陨晶,yuv污染更嚴(yán)重猬仁,我猜應(yīng)該是因?yàn)閟ws轉(zhuǎn)換過(guò)程時(shí)間較長(zhǎng),上面一部分沒污染先誉,下面一部分污染了
另外編譯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、設(shè)置編解碼器上下文參數(shù)
? ? avcodec_context->pix_fmt = AV_PIX_FMT_YUV420P;
? ? avcodec_context->width = width;
? ? avcodec_context->height = width;
? ? // 設(shè)置幀率25fps
? ? avcodec_context->time_base = (AVRational){1, 25};
? ? avcodec_context->framerate = (AVRational){25, 1};
? ? // 設(shè)置碼率
? ? avcodec_context->bit_rate = 4096000;
? ? // 設(shè)置GOP
? ? avcodec_context->gop_size = 250;
? ? avcodec_context->max_b_frames = 0; //必須是0铃芦,否則Mac&iOS無(wú)法播放
? ? 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雅镊、內(nèi)存空間填充
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);
循環(huán)處理圖片序列:
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
下面是視頻里圖片淡入淡出過(guò)程的截圖襟雷,有奇怪的半塊灰色蒙層