ijkplayer阅读笔记07-视频流程

本节主要讲解视频流程,流程如下:

读取视频包 ------> 解码  ------> 显示

视频流程:

1)读取线程:读取视频包,推入videoq队列中
read_thread{
    ret = stream_component_open(ffp, st_index[AVMEDIA_TYPE_VIDEO]);{
        is->video_tid = SDL_CreateThreadEx(&is->_video_tid, video_thread, ffp, "ff_video_dec");
    }

    for (;;) {
        if (is->abort_request)
            break;

        ret = av_read_frame(ic, pkt);
        packet_queue_put(&is->videoq, pkt);   //将获取到的视频包推入videoq队列中
    }
}


2)解码线程
软解:从videoq队列中获取视频包,解码视频帧放入pictq列表中
硬解:从videoq队列中获取视频包,推送MediaCodec解码,获取解码outputbuffer index并存储在pictq列表中
video_thread{
    ffpipenode_run_sync(ffp->node_vdec);{
        node->func_run_sync(node);{ // decoder_from_android_mediacodec 硬解流程
            SDL_CreateThreadEx(enqueue_thread_func){
                while (!q->abort_request) {
                    feed_input_buffer{ 
                        ffp_packet_queue_get_or_buffering
                        SDL_AMediaCodec_dequeueInputBuffer
                        input_buffer_ptr = SDL_AMediaCodec_getInputBuffer
                        memcpy(input_buffer_ptr, d->pkt_temp.data, copy_size);
                        SDL_AMediaCodec_queueInputBuffer
                    }
                }
            }
            while{
                drain_output_buffer{
                     output_buffer_index = SDL_AMediaCodec_dequeueOutputBuffer   
                }
            }
        }
    }



    node->func_run_sync(node);{ // decoder_from_ffplay 软解流程
        func_run_sync{
            ffp_video_thread{
                ffplay_video_thread{
                     for (;;) {
                         get_video_frame(ffp, frame);{
                             decoder_decode_frame(ffp, &is->viddec, frame){
                                  avcodec_decode_video2(d->avctx, frame, &got_frame);
                                  || avcodec_decode_audio4(d->avctx, frame, &got_frame);
                             }
                         }
                         queue_picture(ffp, frame, pts, duration){
                             vp = frame_queue_peek_writable(&is->pictq);
                             SDL_VoutFFmpeg_ConvertFrame(vp->bmp, src_frame){
                      
                             }
                         }
                         frame_queue_push(&is->pictq);
                     }
                }
            }
        }
    }
}


3)显示线程
硬解:由MediaCodec configure Surface,自动完成视频帧的渲染
软解:从pictq列表中获取视频帧,写入nativewindows视频缓冲中渲染
video_refresh_thread {
   IJKFF_Pipenode *node = ffpipeline_open_video_output(ffp->pipeline, ffp);
      ffpipenode_run_sync(node);{
          ffp_video_refresh_thread(opaque->ffp);{
              ffplay_video_refresh_thread{
                  while(!is->abort_request) {
                      video_refresh(ffp, &remaining_time);{
                          video_image_display2{
                             vp = frame_queue_peek(&is->pictq);
                             SDL_VoutDisplayYUVOverlay(ffp->vout, vp->bmp);{
                                 SDL_VoutOverlayAMediaCodec_releaseFrame  or
                                 SDL_Android_NativeWindow_display_l
                             }
                          }
                      }
                  }
              }
          }
      }    
   }
}


你可能感兴趣的:(ffmpeg,android,ijkplayer)