ijkplayer阅读笔记06-音频流程

来源:互联网 发布:摄影网络销售 编辑:程序博客网 时间:2024/05/18 00:05

本节主要介绍音频从读取,到解码,再到播放的流程:

读取音视频数据(文件或流) --> 创建播放线程 --> 创建解码线程 --> 循环读取音频包 --> 推送到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);      }   }}


0 0
原创粉丝点击