IJKPlayer/FFMPEG 4 Android

1 : native_init

    IjkMediaPlayer_native_init : Do nothing.

2 : native_setup

IjkMediaPlayer_native_setup --> ijkmp_android_create(message_loop)
    A: IjkMediaPlayer *mp = ijkmp_create(msg_loop)
        --> mp->ffplayer = ffp_create()
        --> msg_queue_init(&ffp->msg_queue) : Create message queue
        --> mp->msg_loop = msg_loop --> message_loop_n
        --> ijkmp_get_msg
        -->msg_queue_get(&mp->ffplayer->msg_queue, msg, block)
            (prepared, completed, seek_complete, start, pause, seek)
        --> post_event --> JJKC_IjkMediaPlayer__postEventFromNative
        --> (Java) postEventFromNative
    B: mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface();
    C: ffpipeline_create_from_android(mp->ffplayer)
        --> pipeline->func_destroy   = func_destroy;
            pipeline->func_open_video_decoder = func_open_video_decoder
            pipeline->func_open_audio_output  = func_open_audio_output
    D: ffpipeline_set_vout(mp->ffplayer->pipeline, mp->ffplayer->vout)

3: _prepareAsync

--> IjkMediaPlayer_prepareAsync
--> ijkmp_prepare_async
--> ijkmp_prepare_async_l
    A: mp->msg_thread= SDL_CreateThreadEx(&mp->_msg_thread, ijkmp_msg_loop, mp, "ff_msg_loop")
    B: ffp_prepare_async_l
        (1) ffpipeline_open_audio_output --> func_open_audio_output
            --> SDL_AoutAndroid_CreateForOpenSLES
             or 
                SDL_AoutAndroid_CreateForAudioTrack 
                Only get the audio render interface (aout->open_audio, aout->pause_audio, aout->flush_audio, etc)
            --> SDL_AoutSetStereoVolume
        (2) stream_open
            A: frame_queue_init(&is->pictq, &is->videoq, ffp->pictq_size, 1) : **Init video decoded frame buffer queue.**
            B: frame_queue_init(&is->subpq, &is->subtitleq, SUBPICTURE_QUEUE_SIZE, 0) : Init Subtile if needed.
            C: frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1): Init Audio decoded PCM buffer queue.
            D: packet_queue_init(&is->videoq) : Init Video compressed data buffer queue.
            E: packet_queue_init(&is->audioq) : Init Audio compressed data buffer queue.
            F: packet_queue_init(&is->subtitleq) : Init Subtitle compressed data buffer queue if needed.
            G:  init_clock(&is->vidclk, &is->videoq.serial) : Init Video clock
            H: init_clock(&is->audclk, &is->audioq.serial) : Init Audio clock
            I  : init_clock(&is->extclk, &is->extclk.serial) : Init external clock
            J: SDL_CreateThreadEx(&is->_video_refresh_tid, video_refresh_thread, ffp, "ff_vout") --> video_refresh_thread --> video_refresh : Create Video render thread.
            K: SDL_CreateThreadEx(&is->_read_tid, read_thread, ffp, "ff_read") --> read_thread : Create read/input thread.
                1: avformat_alloc_context()
                2: avformat_open_input
                3: avformat_find_stream_info
                4: av_find_best_stream :(Audio/Video/Subtitle)  
                5: stream_component_open(ffp, st_index[AVMEDIA_TYPE_VIDEO])
                    A: avcodec_find_decoder(avctx->codec_id)
                    B: avcodec_open2(avctx, codec, &opts)
                    C: decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread) :Set video compressed buffer queue into created decoder.
                    D: ffpipeline_open_video_decoder 
                                    -- > ffpipenode_create_video_decoder_from_android_mediacodec / ffpipenode_create_video_decoder_from_ffplay
                                        Get decoder interfaces
                    E: decoder_start(&is->viddec, video_thread, ffp, "ff_video_dec")
                    -- > video_thread --> ffpipenode_run_sync 
                    -->  func_run_sync
                    -->  SDL_CreateThreadEx(&opaque->_enqueue_thread, enqueue_thread_func, node, "amediacodec_input_thread")
                    -- > enqueue_thread_func --> feed_input_buffer --> ffp_packet_queue_get_or_buffering : Decoder(MediaCodec) input thread, get compressed data from decoder compressed buffer queue and set into decoder.
                    while (!q->abort_request) -->  : Decoder output thread.
                        drain_output_buffer --> : Drain decoded frame from decoder.
                        ffp_queue_picture --> : Set decoded frame into decoded buffer queue.
                6: stream_component_open(ffp, st_index[AVMEDIA_TYPE_AUDIO])
                    A: codec = avcodec_find_decoder(avctx->codec_id)
                    B: avcodec_open2(avctx, codec, &opts)
                    C: audio_open(ffp, channel_layout, nb_channels, sample_rate, &is->audio_tgt)--> aout_open_audio_n --> Creaete Android_AudioTrack --> start audio_render_thread : aout_thread --> aout_thread_n --> while (!opaque->abort_request)  --> audio_cblk(userdata, buffer, copy_size) : Get decoded PCM data--> Android_AudioTrack_write : Write into Android AudioTrack
                    D: SDL_AoutSetDefaultLatencySeconds
            7: stream_component_open(ffp, st_index[AVMEDIA_TYPE_SUBTITLE])
                                TODO
            8: for (;;) --> Do read/input thread.
                A: is->abort_request : Abort, exit read thread.
                B: is->seek_req : Seek if needed.
                C: av_read_frame(ic, pkt) : Read compressed data.
                D: pb_eof : Deal with EOS.
                E: pkt->stream_index == is->audio_stream --> Put the compressed data into right compressed buffer queue.

4: _start

IjkMediaPlayer_start --> ijkmp_start --> ijkmp_start_l
    --> ffp_notify_msg1(mp->ffplayer, FFP_REQ_START) --> ijkmp_get_msg
    -->FFP_REQ_START--> ffp_start_from_l --> ffp_toggle_buffering 
        --> ffp_seek_to_l
    or
        --> ffp_start_l --> toggle_pause(ffp, 0) --> toggle_pause_l
    -->is->pause_req = pause_on --> set_clock --> is->paused = 0
    -->SDL_AoutPauseAudio ...
    --> ijkmp_change_state_l(mp, MP_STATE_STARTED)

5: _stop

IjkMediaPlayer_stop
    A(1): ijkmp_stop --> ijkmp_stop_l --> ffp_remove_msg --> ffp_stop_l
    --> is->abort_request = 1 --> msg_queue_abort --> q->abort_request = 1
        1: q->abort_request == 1 --> msg_queue_get return -1 --> ijkmp_get_msg return -1 -->  message_loop_n break --> message thread exit
        2: is->abort_request = 1 
            A: video_refresh_thread while (!is->abort_request)
                --> video render exit
            B: read_thread is->abort_request break;
                 --> input thread exit
    B: ijkmp_dec_ref_p --> ijkmp_dec_ref // Not Do This normally 
        1: ijkmp_shutdown --> ijkmp_shutdown_l
            A: ffp_stop_l --> to A(1)
            B: ffp_wait_stop_l --> ffp_stop_l --> A(1) --> stream_close 
                1: packet_queue_abort(&is->videoq)
                    -- > q->abort_request = 1                       
                    A: video_decoder_input_thread : enqueue_thread_func decoder->queue->abort_request  exit (MediaCodec)
                    B: video_decoder_output_thread : func_run_sync decoder->queue->abort_request  exit (MediaCodec)
                2: packet_queue_abort(&is->audioq)
                    --> q->abort_request = 1
                    A: opaque->abort_request
                        --> Audio render thread exit.
                    B: decoder->queue->abort_request
                        --> decoder_decode_frame return -1 
                        --> audio_thread goto the_end
                            --> Audio decoder thread exit

6:_pause

IjkMediaPlayer_pause --> ijkmp_pause --> ijkmp_pause_l
    --> ffp_notify_msg1(mp->ffplayer, FFP_REQ_PAUSE) --> ijkmp_msg_loop
    --> ijkmp_get_msg
        --> msg_queue_get --> FFP_REQ_PAUSE --> ffp_pause_l
        --> toggle_pause(ffp, 1) --> toggle_pause_l --> is->pause_req = 1
        --> stream_toggle_pause_l(ffp, 1)
        --> set_clock 
        --> is->paused = 1
        A: if (is->show_mode != SHOW_MODE_NONE && (!is->paused || is->force_refresh)) : Pause Video render thread
        B: is->paused --> SDL_Delay(10) continue : Pause read thread
        --> SDL_AoutPauseAudio(ffp->aout, pause_on)
            A: SDL_Android_AudioTrack_pause(env, atrack)
            --> aout->pause_audio --> aout_pause_audio
            --> opaque->pause_on = pause_on(true)
            --> while()
            --> if(opaque->pause_on)
            --> SDL_CondWaitTimeout(opaque->wakeup_cond, opaque->wakeup_mutex ,1000)
                **Pause Audio render thread**
            B: sdl_audio_callback --> audio_decode_frame
            --> if (is->paused || is->step) return -1
                : **NOT fill the audio output buffer.**

7 _release

IjkMediaPlayer_release
    A: ijkmp_android_set_surface --> ijkmp_android_set_surface
    --> ijkmp_android_set_surface_l
        1: SDL_VoutAndroid_SetAndroidSurface
            --> SDL_VoutAndroid_SetNativeWindow
            --> SDL_VoutAndroid_SetNativeWindow_l 
            --> SDL_VoutAndroid_invalidateAllBuffers_l
                : Release all output buffers.
            --> vout->opaque->native_window = NULL;
        2: ffpipeline_set_surface --> SDL_VoutAndroid_setAMediaCodec
            --> SDL_VoutAndroid_setAMediaCodec_l
            --> SDL_VoutAndroid_invalidateAllBuffers_l
                : Release all output buffers.
            --> SDL_AMediaCodec_decreaseReferenceP
            --> SDL_AMediaCodec_decreaseReference
            --> if(refCount == 1)SDL_AMediaCodec_delete
            --> *acodec = NULL
            --> vout->opaque->acodec = acodec(NULL)
            --> pipeline->opaque->jsurface = NULL
            --> pipeline->opaque->is_surface_need_reconfigure = true
            --> SDL_JNI_DeleteGlobalRefP(env, &prev_surface)
                : Release pre-surface
    B: ijkmp_shutdown -->ijkmp_shutdown_l
        1: ffp_stop_l --> ...
        2: ffp_wait_stop_l
            A: ffp_stop_l
            B: stream_close
                1: packet_queue_abort(&is->videoq)
                    : Abort video packet queue and
                      effect video decoder thread exit.
                2: packet_queue_abort(&is->audioq)
                    : Abort audio packet queue and
                      effect audio decoder thread exit.
                3: SDL_WaitThread(is->read_tid, NULL)
                    : Read thread exit.
                4: stream_component_close(ffp, is->audio_stream)
                    A: decoder_abort
                        1: packet_queue_abort(d->queue)
                            : Abort audio packet queue and
                             effect video decoder thread exit.
                        2: SDL_WaitThread(d->decoder_tid, NULL)
                            : Exit decoder thread
                        3: packet_queue_flush(d->queue)
                    B: SDL_AoutCloseAudio
                        1: aout->opaque->abort_request = true
                        2: SDL_WaitThread(opaque->audio_tid, NULL)
                            : Exit audio render thread.
                    C: decoder_destroy
                5: stream_component_close(ffp, is->video_stream)
                    A: decoder_abort(&is->viddec, &is->pictq)
                        1: packet_queue_abort(d->queue)
                        2: SDL_WaitThread(d->decoder_tid, NULL)
                            : Exit video decoder thread.
                        3: packet_queue_flush(d->queue)
                    B: decoder_destroy
                6: stream_component_close(ffp, is->subtitle_stream)
                    TODO
                7: avformat_close_input
                8: SDL_WaitThread(is->video_refresh_tid, NULL)
                    : Video render thread exit
                9:  packet_queue_destroy(&is->videoq)
            10: packet_queue_destroy(&is->audioq)
            11: packet_queue_destroy(&is->subtitleq)                                                                                                                                  
            12: frame_queue_destory(&is->pictq)
            13: frame_queue_destory(&is->sampq)
            14: frame_queue_destory(&is->subpq)
        C: jni_set_media_player(env, thiz, NULL)
D: jni_set_media_data_source(env, thiz, NULL)
E: ijkmp_dec_ref_p(&mp)
     ijkmp_dec_ref_p --> ijkmp_dec_ref  // NOT Do this usually. 
        1: ijkmp_shutdown --> ijkmp_shutdown_l
            A: ffp_stop_l --> to A(1)
            B: ffp_wait_stop_l --> ffp_stop_l --> A(1)
                --> stream_close
                1: packet_queue_abort(&is->videoq)
                -- > q->abort_request = 1                       
                    A: video_decoder_input_thread
                        : enqueue_thread_func decoder->
                        queue->abort_request  exit (MediaCodec)
                    B: video_decoder_output_thread
                        : func_run_sync decoder->
                        queue->abort_request  exit (MediaCodec)
                2: packet_queue_abort(&is->audioq)
                  q->abort_request = 1
                    A: opaque->abort_request
                        :Audio render thread exit.
                    B: decoder->queue->abort_request
                    --> decoder_decode_frame return -1
                    --> audio_thread goto the_end
                    --> Audio decoder thread exit

8: _reset

IjkMediaPlayer_reset
    A: IjkMediaPlayer_release(env, thiz);
    B: IjkMediaPlayer_native_setup(env, thiz, weak_thiz);
    C: ijkmp_dec_ref_p(&mp);

9: seekTo

IjkMediaPlayer_seekTo --> ijkmp_seek_to --> ijkmp_seek_to_l
    A: mp->seek_req = 1
    B: mp->seek_msec = msec
    C: ffp_remove_msg(mp->ffplayer, FFP_REQ_SEEK)
    D: ffp_notify_msg2(mp->ffplayer, FFP_REQ_SEEK, (int)msec)
    E: mp->msg_loop = msg_loop --> message_loop_n -->
       ijkmp_get_msg --> msg_queue_get
        case FFP_REQ_SEEK --> ffp_seek_to_l(mp->ffplayer, msg->arg1)
        --> stream_seek(is, seek_pos, 0, 0)
            1: is->seek_pos = pos;   
            2: is->seek_rel = rel;   
            3: is->seek_flags &= ~AVSEEK_FLAG_BYTE;
            4:  if (seek_by_bytes)    
                    is->seek_flags |= AVSEEK_FLAG_BYTE;
            5: is->seek_req = 1; 
    F: read_thread
        if (is->seek_req) --> seek_target = is->seek_pos
        --> ffp_toggle_buffering(ffp, 1) --> avformat_seek_file
            1: packet_queue_flush(&is->audioq)
                --> packet_queue_put(&is->audioq, &flush_pkt)
            2: packet_queue_flush(&is->subtitleq)
                --> packet_queue_put(&is->subtitleq, &flush_pkt)
            3: ffpipenode_flush(ffp->node_vdec)
                --> packet_queue_flush(&is->videoq)
                --> packet_queue_put(&is->videoq, &flush_pkt)
            4: set_clock
            5: ffp_notify_msg1(ffp, FFP_MSG_SEEK_COMPLETE)
            6: ffp_toggle_buffering(ffp, 1)

             Go on read_thread ...

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