SailorHub

iOS-音视频(二十九) : ijkplayer阅读笔记

视频流程:

 

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

                            }

                        }

                    }

                }

            }

        }

    }

}

}

[cpp] view plain copy

视频流程:

 

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

                            }

                        }

                    }

                }

            }

        }

    }

}

}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注