美文网首页
十五、视频解码原理MP4转YUV420P

十五、视频解码原理MP4转YUV420P

作者: ChiangCMBA | 来源:发表于2018-04-24 07:13 被阅读0次

    视频解码原理MP4转YUV420P

    #include <jni.h>
    #include <string>
    #include <android/log.h>
    
    extern "C"{
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libswscale/swscale.h"
    }
    
    #define LOGI(FORMAT, ...) __android_log_print(ANDROID_LOG_INFO, "FFmpegDecoder", FORMAT, ##__VA_ARGS__);
    #define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR, "FFmpegDecoder", FORMAT, ##__VA_ARGS__);
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_fmtech_ffmpegdecoder_MainActivity_mp4ToYuv(JNIEnv *env, jobject instance,
                                                        jstring inputPath_, jstring outPutPath_) {
        const char *inputPath = env->GetStringUTFChars(inputPath_, 0);
        const char *outPutPath = env->GetStringUTFChars(outPutPath_, 0);
    
        av_register_all();
    
        AVFormatContext *pContext = avformat_alloc_context();
    
        //Open an input stream and read the header. The codecs are not opened.
        if(avformat_open_input(&pContext, inputPath, NULL, NULL) < 0){
            LOGE("Open input failed.");
            return;
        }
    
    
        //Read packets of a media file to get stream information.
        if(avformat_find_stream_info(pContext, NULL) < 0){
            LOGE("Get stream information failed.");
            return;
        }
    
        int video_stream_idx = -1;
        //Find video stream
        for(int i=0; i < pContext->nb_streams; i++){
            if(pContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
                video_stream_idx = i;
            }
        }
    
        AVCodecContext *pCodecCtx = pContext->streams[video_stream_idx]->codec;
    
        AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
        if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0){
            LOGE("avcodec open failed.");
            return;
        }
    
        AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));
        av_init_packet(packet);
    
        AVFrame *frame = av_frame_alloc();
        AVFrame *yuvFrame = av_frame_alloc();
    
        uint8_t *out_buffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));
    
        /**
        * Setup the picture fields based on the specified image parameters
        * and the provided image data buffer.
        */
        int re = avpicture_fill((AVPicture*)yuvFrame, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);
    
        SwsContext *swsContext = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                                                pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,
                                                SWS_BILINEAR, NULL, NULL, NULL);
    
        int frameCount = 0;
        FILE *fp_yuv = fopen(outPutPath, "wb");
    
        int got_frame;
        while(av_read_frame(pContext, packet) >= 0){
            avcodec_decode_video2(pCodecCtx, frame, &got_frame, packet);
    
            if(got_frame > 0){
                /**
                * Scale the image slice in srcSlice and put the resulting scaled
                * slice in the image in dst. A slice is a sequence of consecutive
                * rows in an image.
                */
                sws_scale(swsContext, (const uint8_t *const *) frame->data, frame->linesize, 
                0, frame->height, yuvFrame->data, yuvFrame->linesize);
    
                int y_size = pCodecCtx->width * pCodecCtx->height;
                fwrite(yuvFrame->data[0], 1, y_size, fp_yuv);
                fwrite(yuvFrame->data[1], 1, y_size/4, fp_yuv);
                fwrite(yuvFrame->data[2], 1, y_size/4, fp_yuv);
            }
    
            av_free_packet(packet);
        }
    
        fclose(fp_yuv);
        av_frame_free(&frame);
        av_frame_free(&yuvFrame);
        avcodec_close(pCodecCtx);
        avformat_free_context(pContext);
    
        env->ReleaseStringUTFChars(inputPath_, inputPath);
        env->ReleaseStringUTFChars(outPutPath_, outPutPath);
    }
    

    【相关源码】

    相关文章

      网友评论

          本文标题:十五、视频解码原理MP4转YUV420P

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