ijkplayer阅读笔记06-音频流程
2015-08-17 11:03
127 查看
本节主要介绍音频从读取,到解码,再到播放的流程:
读取音视频数据(文件或流) --> 创建播放线程 --> 创建解码线程 --> 循环读取音频包 --> 推送到is->audioq ---> audio_thread从audioq获取音频包解码并推送到sampq --> aout_thread 从 sampq获取解码好的音频帧,推送到AudioTrack播放
读取音视频数据(文件或流) --> 创建播放线程 --> 创建解码线程 --> 循环读取音频包 --> 推送到is->audioq ---> audio_thread从audioq获取音频包解码并推送到sampq --> aout_thread 从 sampq获取解码好的音频帧,推送到AudioTrack播放
音频解码流程:从文件或流中读取音频包,推送到is->audioq队列中 1)读取线程 read_thread{ avformat_open_input avformat_find_stream_info for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; enum AVMediaType type = st->codec->codec_type; st_index[type] = i; } st_index[AVMEDIA_TYPE_AUDIO] = av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, st_index[AVMEDIA_TYPE_AUDIO], st_index[AVMEDIA_TYPE_VIDEO], NULL, 0); if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { ret = stream_component_open(ffp, st_index[AVMEDIA_TYPE_VIDEO]);{ Vid eoState *is = ffp->is; AVFormatContext *ic = is->ic; AVCodecContext *avctx; AVCodec *codec; avctx = ic->streams[stream_index]->codec; codec = avcodec_find_decoder(avctx->codec_id); audio_open(ffp, channel_layout, nb_channels, sample_rate, &is->audio_tgt);{ wanted_spec.callback = sdl_audio_callback; wanted_spec.userdata = opaque; SDL_AoutOpenAudio(ffp->aout, &wanted_spec, &spec){ aout->open_audio(aout, desired, obtained);{ aout_open_audio_n{ // aout_thread 线程从解码好的音频帧队列sampq中,循环取数据推入AudioTrack中播放 SDL_CreateThreadEx(&opaque->_audio_tid, aout_thread);{ } } } } } is->audio_stream = stream_index; is->audio_st = ic->streams[stream_index]; is->audio_tid = SDL_CreateThreadEx(&is->_audio_tid, audio_thread, ffp, "ff_audio_dec"); //创建音频解码线程,从audioq队列中获取音频包,解码并加入sampq音频帧列表中 } } for (;;) { ret = av_read_frame(ic, pkt); packet_queue_put(&is->audioq, pkt); //读取音频帧,推送到音频帧队列is->aidopq中 } } 2)音频解码线程:从is->audioq中获取音频包解码,推送到音频解码帧列表is->sampq中 audio_thread{ do { decoder_decode_frame(ffp, &is->auddec, frame, NULL){ packet_queue_get_or_buffering(ffp, d->queue, &pkt) avcodec_decode_audio4 } af = frame_queue_peek_writable(&is->sampq) av_frame_move_ref(af->frame, frame); frame_queue_push(&is->sampq); } } 3)音频播放线程:从音频解码帧列表中is->sampq获取解码帧,推送到AudioTrack播放 aout_thread{ aout_thread_n{ while (!opaque->abort_request) { audio_cblk(userdata, buffer, copy_size);{ sdl_audio_callback(void *opaque, Uint8 *stream, int len){ while (len > 0) { audio_size = audio_decode_frame(ffp);{ af = frame_queue_peek_readable(&is->sampq) is->audio_buf = af->frame->data[0]; } memcpy(stream, (uint8_t *)is->audio_buf+is->audio_buf_index, len1); } } } SDL_Android_AudioTrack_write_byte(env, atrack, buffer, copy_size); } } }
相关文章推荐
- vijos - P1319数列 (二进制 + 找规律 + python)
- string get_telno(string &userid) 和 string get_telno(string userid) 有什么区别
- JAVA文件扫描(递归)
- 剑指offer——面试题24:二叉搜索树的后续遍历序列
- [LeetCode]Sliding Window Maximum
- 用VS发布的程序,如何让快捷方式指向exe而不是msi文件
- ckeditor换kama皮肤
- hash + bsgs模板
- POJ3667 Hotel
- F
- Python Web Scraper - Simple Url Request
- writing a usb driver(在国外的网站上复制下来的)
- Android学习系列--App调试内存泄露之Context篇(上)
- 戦後70年に問う―個人を尊重する国の約束
- iOS学习笔记(一)
- Android触摸事件分发与响应
- 带关闭按钮的右下角图片广告
- Comparator排序集合
- Kaggle入门——使用scikit-learn解决DigitRecognition问题
- Android 开源项目第一篇——个性化控件(View)篇