IJKPlayer/FFMPEG 4 Android
16lz
2021-01-23
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 ...
更多相关文章
- 代码中设置drawableleft
- android 3.0 隐藏 系统标题栏
- Android开发中activity切换动画的实现
- Android(安卓)学习 笔记_05. 文件下载
- Android中直播视频技术探究之—摄像头Camera视频源数据采集解析
- 技术博客汇总
- android 2.3 wifi (一)
- AndRoid Notification的清空和修改
- Android中的Chronometer