视频解码流程

视频解码流程

流程图:
视频解码流程图.png
  1. 注册组件
    av_register_all();

  2. 打开文件
    avformat_open_input();

  3. 查找视频流
    avformat_find_stream_info();

  4. 查找视频解码器

  5. 打开解码器
    avcodec_open2();

  6. 读取视频压缩数据

  7. 视频解码

  8. 关闭解码器-〉解码完成

示例:

+(void) ffmepgVideoDecode:(NSString*)inFilePath outFilePath:(NSString*)outFilePath{

    av_register_all();

    AVFormatContext *avformat_context = avformat_alloc_context();

    const char *url = [inFilePath UTF8String];

    int avformat_open_input_result = avformat_open_input(&avformat_context, url, NULL, NULL);
    if (avformat_open_input_result != 0) {
        NSLog(@"打开文件失败!");
        return;
    }

    int avformat_find_stream_info_result = avformat_find_stream_info(avformat_context, NULL);
    if (avformat_find_stream_info_result < 0) {
        NSLog(@"查找失败!");
        return;
        
    }
    
    int av_stream_index = -1;
    for (int i = 0; i < avformat_context->nb_streams; ++i) {

        if(avformat_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
            av_stream_index = i;
            break;
        }
    }
    
    AVCodecContext *avcodec_context = avformat_context->streams[av_stream_index]->codec;

    AVCodec *avcodec = avcodec_find_decoder(avcodec_context->codec_id);
    int avcodec_open2_result = avcodec_open2(avcodec_context, avcodec, NULL);
    if (avcodec_open2_result != 0) {
        NSLog(@"打开解码器失败!");
        return;
    }
    
    NSLog(@"解码器名称:%s",avcodec->name);
    AVPacket *packet = (AVPacket*)av_malloc(sizeof(AVPacket));
    AVFrame *avframe_in = av_frame_alloc();
    int decode_result = -1;
  
    struct SwsContext *swscontext = sws_getContext(avcodec_context->width,
                   avcodec_context->height,
                   avcodec_context->pix_fmt,
                   avcodec_context->width,
                   avcodec_context->height,
                   AV_PIX_FMT_YUV420P,
                   SWS_BICUBIC,
                   NULL,
                   NULL,
                   NULL);
   
    AVFrame *avframe_yuv420p = av_frame_alloc();
    int buffer_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,
                                               avcodec_context->width,
                                               avcodec_context->height,
                                               1);
   
    uint8_t *out_buffer = (uint8_t*)av_malloc(buffer_size);
    
    av_image_fill_arrays(avframe_yuv420p->data,
                         avframe_yuv420p->linesize,
                         out_buffer,
                         AV_PIX_FMT_YUV420P,
                         avcodec_context->width,
                         avcodec_context->height,
                         1);
    

    int y_size,u_size,v_size;
   
    const char *outfile = [outFilePath UTF8String];
    FILE *file_yuv420p = fopen(outfile, "wb+");
    if (file_yuv420p == NULL) {
        NSLog(@"输出文件打开失败");
        return;
    }
    
    int current_index = 0;
    
    while (av_read_frame(avformat_context, packet) >= 0) {
      
        if (packet->stream_index == av_stream_index){
            
        
            avcodec_send_packet(avcodec_context, packet);
           
            decode_result = avcodec_receive_frame(avcodec_context, avframe_in);
            if (decode_result == 0) {
       
                sws_scale(swscontext,
                          (const uint8_t *const *)avframe_in->data,
                          avframe_in->linesize,
                          0,
                          avcodec_context->height,
                          avframe_yuv420p->data,
                          avframe_yuv420p->linesize);
                
     
                y_size = avcodec_context->width * avcodec_context->height;
                u_size = y_size / 4;
                v_size = y_size / 4;
                
                fwrite(avframe_yuv420p->data[0], 1, y_size, file_yuv420p);
                fwrite(avframe_yuv420p->data[1], 1, u_size, file_yuv420p);
                fwrite(avframe_yuv420p->data[2], 1, v_size, file_yuv420p);

                current_index ++;
                NSLog(@"当前解码第%d帧",current_index);
  
            }
            
        }
    }
   
    av_packet_free(&packet);
    fclose(file_yuv420p);
    av_frame_free(&avframe_in);
    av_frame_free(&avframe_yuv420p);
    free(out_buffer);
    avcodec_close(avcodec_context);
    avformat_free_context(avformat_context);
    
}

你可能感兴趣的:(视频解码流程)