static int dt_transport_event (event_t * event, dt_server_mgt_t * mgt) { dt_lock (&mgt->server_lock); event_server_t *entry = mgt->server; int ret = 0; while (entry->id != event->server_id) { entry = entry->next; if (!entry) break; } if (!entry) { dt_error (TAG, "Could not found server for:%d \n ", event->server_id); ret = -1; goto FAIL; } ret = dt_add_event (event, entry); if (ret < 0) //we need to free this event { dt_error (TAG, "we can not transport this event, id:%d type:%d\n ", event->server_id, event->type); free (event); ret = -1; goto FAIL; } dt_unlock (&mgt->server_lock); return ret; FAIL: dt_unlock (&mgt->server_lock); return ret; }
int dt_event_server_init () { pthread_t tid; int ret = 0; server_mgt.server = NULL; server_mgt.server_count = 0; server_mgt.exit_flag = 0; dt_lock_init (&server_mgt.server_lock, NULL); main_server.id = EVENT_SERVER_MAIN; strcpy (main_server.name, "SERVER-MAIN"); main_server.event_count = 0; main_server.event = NULL; main_server.next = NULL; dt_lock_init (&main_server.event_lock, NULL); ret = dt_register_server (&main_server); if (ret < 0) { dt_error (TAG, "SERVER REGISTER FAILED \n"); return -1; } ret = pthread_create (&tid, NULL, (void *) &event_transport_loop, NULL); if (ret != 0) { dt_error (TAG, "TRANSTROP LOOP CREATE FAILED \n"); return -1; } server_mgt.transport_loop_id = tid; dt_info (TAG, "TRANSTROP LOOP CREATE OK, TID:%u \n", (unsigned)tid); return 0; }
void *dtplayer_init (dtplayer_para_t * para) { int ret = 0; if (!para) return NULL; player_register_all(); dtplayer_context_t *dtp_ctx = malloc(sizeof(dtplayer_context_t)); // will free in dtplayer.c if (!dtp_ctx) { dt_error (TAG, "dtplayer context malloc failed \n"); return NULL; } memset (dtp_ctx, 0, sizeof (*dtp_ctx)); memcpy (&dtp_ctx->player_para, para, sizeof (dtplayer_para_t)); dt_info(TAG,"start playing :%s \n",para->file_name); /*init player */ ret = player_init (dtp_ctx); if (ret < 0) { dt_error (TAG, "PLAYER INIT FAILED \n"); free(dtp_ctx); dtp_ctx = NULL; } return dtp_ctx; }
//==Part1:Control int dtvideo_init (void **video_priv, dtvideo_para_t * para, void *parent) { int ret = 0; dtvideo_context_t *vctx = (dtvideo_context_t *) malloc (sizeof (dtvideo_context_t)); if (!vctx) { dt_error (TAG, "[%s:%d] video init failed \n", __FUNCTION__, __LINE__); ret = -1; goto ERR0; } memcpy (&vctx->video_para, para, sizeof (dtvideo_para_t)); vctx->video_para.extradata_size = para->extradata_size; memcpy (&(vctx->video_para.extradata[0]), &(para->extradata[0]), para->extradata_size); //we need to set parent early vctx->parent = parent; ret = video_init (vctx); if (ret < 0) { dt_error (TAG, "[%s:%d] dtvideo_mgt_init failed \n", __FUNCTION__, __LINE__); ret = -1; goto ERR1; } *video_priv = (void *) vctx; return ret; ERR1: free (vctx); ERR0: return ret; }
static stream_cache_t * create_cache(int size,float pre) { if(size <= 0) goto ERR0; stream_cache_t *cache = (stream_cache_t *)malloc(sizeof(stream_cache_t)); if(!cache) { dt_error(TAG,"cache ctx failed"); goto ERR0; } memset(cache,0,sizeof(stream_cache_t)); cache->data = (uint8_t *)malloc(size); if(!cache->data) { dt_error(TAG,"cache data malloc failed"); goto ERR1; } cache->total_size = size; cache->fix_pre_size = size * pre; //cache->post_size = size * post; dt_lock_init (&cache->mutex, NULL); dt_info(TAG,"Create cache ok, total:%d fixpresize:%d pre:%f \n",cache->total_size,cache->fix_pre_size,pre); return cache; ERR1: free(cache); ERR0: return NULL; }
int dthost_init (void **host_priv, dthost_para_t * para) { int ret = 0; if (*host_priv) { dt_error (TAG, "[%s:%d] host_priv is Null\n", __FUNCTION__, __LINE__); ret = -1; goto ERR0; } dthost_context_t *hctx = malloc (sizeof (dthost_context_t)); if (!hctx) { dt_info (TAG, "[%s:%d] dthost_context_t malloc failed\n", __FUNCTION__, __LINE__); ret = -1; goto ERR0; } dt_debug (TAG, "hctx :%p \n", hctx); memset (hctx, 0, sizeof (dthost_context_t)); memcpy (&hctx->para, para, sizeof (dthost_para_t)); ret = host_init (hctx); if (ret < 0) { dt_error (TAG, "[%s:%d] dthost_init failed\n", __FUNCTION__, __LINE__); ret = -1; goto ERR1; } *host_priv = (void *) hctx; return ret; ERR1: free (hctx); ERR0: return ret; }
//1 get one frame 0 failed -1 err int ffmpeg_adec_decode(ad_wrapper_t *wrapper, adec_ctrl_t *pinfo) { int got_samples = 0; int ret = 0; int data_size = 0; AVFrame frame_tmp; //AVFrame frame; AVPacket pkt; memset(&pkt, 0, sizeof(AVPacket)); pkt.data = pinfo->inptr; pkt.size = pinfo->inlen; pkt.side_data_elems = 0; memset(&frame_tmp, 0, sizeof(AVFrame)); memset(frame, 0, sizeof(AVFrame)); dtaudio_decoder_t *decoder = (dtaudio_decoder_t *)wrapper->parent; dt_debug(TAG, "start decode size:%d %02x %02x \n", pkt.size, pkt.data[0], pkt.data[1]); ret = avcodec_decode_audio4(avctxp, frame, &got_samples, &pkt); dt_debug(TAG, "start decode size:%d %02x %02x %02x %02x \n", pkt.size, pkt.data[0], pkt.data[1], pkt.data[2], pkt.data[3]); if (ret < 0) { dt_error(TAG, "decode failed ret:%d \n", ret); goto EXIT; } if (!got_samples) { //decode return 0 dt_error(TAG, "get no samples out \n"); pinfo->outlen = 0; goto EXIT; } data_size = av_samples_get_buffer_size(frame->linesize, avctxp->channels, frame->nb_samples, avctxp->sample_fmt, 1); if (data_size > 0) { audio_convert(decoder, &frame_tmp, frame); //out frame too large, realloc out buf if (pinfo->outsize < frame_tmp.linesize[0]) { pinfo->outptr = realloc(pinfo->outptr, frame_tmp.linesize[0] * 2); pinfo->outsize = frame_tmp.linesize[0] * 2; } memcpy(pinfo->outptr, frame_tmp.data[0], frame_tmp.linesize[0]); pinfo->outlen = frame_tmp.linesize[0]; } else { dt_error(TAG, "data_size invalid: size:%d outlen:%d \n", data_size, pinfo->outlen); pinfo->outlen = 0; } EXIT: if (frame_tmp.data[0]) { free(frame_tmp.data[0]); } frame_tmp.data[0] = NULL; return ret; }
int main() { dt_get_log_level(); dt_info("TEST", "this is info level test \n"); dt_error("TEST", "this is error level test \n"); dt_debug("TEST", "this is debug level test \n"); dt_warning("TEST", "this is warnning level test \n"); dt_set_log_level(1); dt_info("TEST", "this is info level test \n"); dt_error("TEST", "this is error level test \n"); dt_debug("TEST", "this is debug level test \n"); dt_warning("TEST", "this is warning level test \n"); return; }
int dt_send_event (event_t * event) { dt_server_mgt_t *mgt = &server_mgt; event_server_t *server_hub = mgt->server; if (!server_hub) { dt_error (TAG, "EVENT SEND FAILED \n"); return -1; } dt_lock (&server_hub->event_lock); if (server_hub->event_count == 0) server_hub->event = event; else { event_t *entry = server_hub->event; while (entry->next) entry = entry->next; entry->next = event; } server_hub->event_count++; dt_unlock (&server_hub->event_lock); dt_debug (TAG, "EVENT:%d SEND OK, event count:%d \n", event->type, server_hub->event_count); return 0; }
static int media_format_convert (const char *name) { int i, j; int type = MEDIA_FORMAT_INVALID; j = sizeof (media_map) / sizeof (type_map_t); for (i = 0; i < j; i++) { if (strcmp (name, media_map[i].key) == 0) { break; } } if (i == j) { for (i = 0; i < j; i++) { if (strstr (name, media_map[i].key) != NULL) { break; } if (i == j) { dt_error ("Unsupport media type %s\n", name); return MEDIA_FORMAT_INVALID; } } } type = media_map[i].value; dt_info (TAG, "name:%s media_type=%d \n", name, type); return type; }
int audio_output_init(dtaudio_output_t * ao, int ao_id) { int ret = 0; pthread_t tid; /*select ao device */ ret = select_ao_device(ao, ao_id); if (ret < 0) { return -1; } ao_wrapper_t *wrapper = ao->wrapper; memcpy(&wrapper->para, &ao->para, sizeof(dtaudio_para_t)); wrapper->init(wrapper); dt_info(TAG, "[%s:%d] audio output init success\n", __FUNCTION__, __LINE__); /*start aout pthread */ ret = pthread_create(&tid, NULL, audio_output_thread, (void *) ao); if (ret != 0) { dt_error(TAG, "[%s:%d] create audio output thread failed\n", __FUNCTION__, __LINE__); return ret; } ao->output_thread_pid = tid; dt_info(TAG, "[%s:%d] create audio output thread success\n", __FUNCTION__, __LINE__); return ret; }
static int stream_file_open(stream_wrapper_t * wrapper, char *stream_name) { int fd = -1; file_ctx_t *ctx = malloc(sizeof(*ctx)); stream_ctrl_t *info = &wrapper->info; memset(info, 0, sizeof(*info)); fd = open(stream_name, O_RDONLY); if (fd < 0) { dt_error(TAG, "OPEN FILE FAILED \n"); return -1; } ctx->fd = fd; struct stat state; if (stat(stream_name, &state) < 0) { ctx->file_size = -1; } else { ctx->file_size = state.st_size; } wrapper->stream_priv = (void *)ctx; info->stream_size = ctx->file_size; info->is_stream = 0; info->seek_support = 1; info->cur_pos = 0; return DTERROR_NONE; }
static int demuxer_ffmpeg_open (demuxer_wrapper_t * wrapper) { AVFormatContext *ic = NULL; int err, ret; dtdemuxer_context_t *ctx = (dtdemuxer_context_t *)wrapper->parent; char *file_name = ctx->file_name; av_register_all (); err = avformat_open_input (&ic, file_name, NULL, NULL); if (err < 0) return -1; dt_info (TAG, "[%s:%d] avformat_open_input ok\n", __FUNCTION__, __LINE__); wrapper->demuxer_priv = (void *) ic; err = avformat_find_stream_info (ic, NULL); if (err < 0) { dt_error (TAG, "%s: could not find codec parameters\n", file_name); ret = -1; goto FAIL; } dt_info (TAG, "[%s:%d] start_time:%lld \n", __FUNCTION__, __LINE__, ic->start_time); return 0; FAIL: avformat_close_input (&ic); return ret; }
int video_decoder_init (dtvideo_decoder_t * decoder) { int ret = 0; pthread_t tid; /*select decoder */ ret = select_video_decoder (decoder); if (ret < 0) return -1; vd_wrapper_t *wrapper = decoder->wrapper; /*init decoder */ decoder->pts_current = decoder->pts_first = -1; decoder->vd_priv = decoder->para.avctx_priv; ret = wrapper->init (decoder); if (ret < 0) return -1; pts_mode = 0; char value[512]; if(GetEnv("VIDEO","pts.mode",value) > 0) { pts_mode = atoi(value); dt_info(TAG,"pts mode:%d fps:%f \n",pts_mode,decoder->para.fps); } dt_info (TAG, "[%s:%d] video decoder init ok\n", __FUNCTION__, __LINE__); /*init pcm buffer */ dtvideo_context_t *vctx = (dtvideo_context_t *) decoder->parent; vctx->vo_queue = queue_new (); queue_t *picture_queue = vctx->vo_queue; if (NULL == picture_queue) { dt_error (TAG, "create video out queue failed\n"); return -1; } /*create thread */ ret = pthread_create (&tid, NULL, video_decode_loop, (void *) decoder); if (ret != 0) { dt_error (TAG, "create audio decoder thread failed\n"); return ret; } decoder->video_decoder_pid = tid; video_decoder_start (decoder); //decoder->status=ADEC_STATUS_RUNNING;//start decode after init return 0; }
/*********************************************************************** ** ** Process one frame with ffmpeg-libavfilter ** ***********************************************************************/ static int convert_picture(vf_wrapper_t * wrapper, dt_av_frame_t * src) { uint8_t *buffer; int buffer_size; vf_ffmpeg_ctx_t *vf_ctx = (vf_ffmpeg_ctx_t *)(wrapper->vf_priv); dtvideo_para_t *para = &wrapper->para; int sw = para->s_width; int dw = para->d_width; int sh = para->s_height; int dh = para->d_height; int sf = para->s_pixfmt; int df = para->d_pixfmt; if (!vf_ctx->swap_frame) { vf_ctx->swap_frame = (dt_av_frame_t *)malloc(sizeof(dt_av_frame_t)); } dt_av_frame_t *pict = vf_ctx->swap_frame; if (!pict) { dt_error(TAG, "[%s:%d] err: swap frame malloc failed \n", __FUNCTION__, __LINE__); return -1; } memset(pict, 0, sizeof(dt_av_frame_t)); AVPicture *dst = (AVPicture *)pict; buffer_size = avpicture_get_size(df, dw, dh); if (buffer_size > vf_ctx->swap_buf_size) { if (vf_ctx->swapbuf) { free(vf_ctx->swapbuf); } vf_ctx->swap_buf_size = buffer_size; vf_ctx->swapbuf = (uint8_t *) malloc(buffer_size * sizeof(uint8_t)); } buffer = vf_ctx->swapbuf; avpicture_fill((AVPicture *) dst, buffer, df, dw, dh); vf_ctx->pSwsCtx = sws_getCachedContext(vf_ctx->pSwsCtx, sw, sh, sf, dw, dh, df, SWS_BICUBIC, NULL, NULL, NULL); sws_scale(vf_ctx->pSwsCtx, src->data, src->linesize, 0, sh, dst->data, dst->linesize); pict->pts = src->pts; pict->width = dw; pict->height = dh; pict->pixfmt = df; if (src->data) { free(src->data[0]); } memcpy(src, pict, sizeof(dt_av_frame_t)); vf_ctx->swapbuf = NULL; vf_ctx->swap_buf_size = 0; return 0; }
int video_start (dtvideo_context_t * vctx) { if (vctx->video_status == VIDEO_STATUS_INITED) { dtvideo_output_t *video_out = &vctx->video_out; video_output_start (video_out); vctx->video_status = VIDEO_STATUS_ACTIVE; } else dt_error (TAG, "[%s:%d]video output start failed \n", __FUNCTION__, __LINE__); return 0; }
int dthost_write_frame (void *host_priv, dt_av_pkt_t * frame, int type) { int ret = 0; if (!host_priv) { dt_error (TAG, "[%s:%d] host_priv==NULL \n", __FUNCTION__, __LINE__); return -1; } dthost_context_t *hctx = (dthost_context_t *) (host_priv); ret = host_write_frame (hctx, frame, type); return ret; }
int dthost_get_out_closed (void *host_priv) { int ret = 0; if (!host_priv) { dt_error (TAG, "host PRIV IS NULL \n"); return -1; } dthost_context_t *hctx = (dthost_context_t *) host_priv; ret = host_get_out_closed (hctx); return ret; }
static int stream_cache_seek (stream_wrapper_t * wrapper, int64_t pos, int whence) { int ret = 0; cache_ctx_t *ctx = (cache_ctx_t *)wrapper->stream_priv; stream_cache_t *cache = ctx->cache; stream_wrapper_t *real_st = ctx->wrapper; stream_ctrl_t *info = &wrapper->info; info->eof_flag = 0; dt_info(TAG,"Enter cache seek \n"); // ret stream size if(whence == AVSEEK_SIZE) { dt_debug(TAG,"REQUEST STREAM SIZE:%lld \n",info->stream_size); return info->stream_size; } int step; int orig; if(whence == SEEK_SET) { step = abs(info->cur_pos - pos); orig = (info->cur_pos > pos)?0:1; } if(whence == SEEK_CUR) { step = abs(pos); orig = (pos < 0)?0:1; } if(cache_seek(cache,step,orig) == 0) // seek in cache { dt_info(TAG,"cache seek success \n"); } else // seek through real stream ops { pause_cache_thread(ctx); ret =real_st->seek(real_st,pos,whence); // fixme: seek maybe failed for online video if(ret != DTERROR_NONE) { dt_error(TAG,"SEEK FAILED \n"); } cache_reset(ctx->cache); resume_cache_thread(ctx); } info->eof_flag = 0; if(whence == SEEK_SET) info->cur_pos = pos; if(whence == SEEK_CUR) info->cur_pos += pos; return ret; }
static int select_video_decoder (dtvideo_decoder_t * decoder) { vd_wrapper_t **p; p = &g_vd; if (!*p) { dt_error (TAG, "[%s:%d] select no video decoder \n", __FUNCTION__, __LINE__); return -1; } decoder->wrapper = *p; dt_info (TAG, "[%s:%d] select--%s video decoder \n", __FUNCTION__, __LINE__, (*p)->name); return 0; }
event_t *dt_alloc_event () { event_t *event = (event_t *) malloc (sizeof (event_t)); if (!event) { dt_error (TAG, "EVENT ALLOC FAILED \n"); return NULL; } event->next = NULL; event->server_id = -1; event->type = -1; return event; }
int dt_send_event_sync (event_t * event) { dt_server_mgt_t *mgt = &server_mgt; event_server_t *server_hub = mgt->server; if (!server_hub) { dt_error (TAG, "EVENT SEND FAILED \n"); return -1; } dt_transport_event (event, mgt); dt_debug (TAG, "EVENT:%d BYPASS SEND OK \n"); return 0; }
int dt_register_server (event_server_t * server) { dt_server_mgt_t *mgt = &server_mgt; int ret = 0; if (!mgt) { dt_error (TAG, "SERVICE MGT IS NULL\n"); return -1; } dt_lock (&mgt->server_lock); if (mgt->server_count == 0) mgt->server = server; event_server_t *entry = mgt->server; while (entry->next != NULL) { if (entry->id == server->id) { dt_error (TAG, "SERVICE HAS BEEN REGISTERD BEFORE\n"); ret = -1; goto FAIL; } entry = entry->next; } if (entry->next == NULL) { entry->next = server; server->next = NULL; mgt->server_count++; } dt_unlock (&mgt->server_lock); dt_info (TAG, "SERVICE:%s REGISTER OK,SERVERCOUNT:%d \n", server->name, mgt->server_count); return 0; FAIL: dt_unlock (&mgt->server_lock); return ret; }
int stream_open (dtstream_context_t * stm_ctx) { int ret = 0; if (stream_select (stm_ctx) == -1) { dt_error (TAG, "select stream failed \n"); return -1; } stream_wrapper_t *wrapper = stm_ctx->stream; memset(&wrapper->info,0,sizeof(stream_ctrl_t)); dt_info (TAG, "select stream:%s\n", wrapper->name); //stream buffer eanble check char value[512]; int cache_enable = 0; if(GetEnv("STREAM","stream.cache",value) > 0) { cache_enable = atoi(value); dt_info(TAG,"cache enable:%d \n",cache_enable); } else dt_info(TAG,"cache enable not set, use default:%d \n",cache_enable); if(cache_enable) { extern stream_wrapper_t stream_cache; wrapper = &stream_cache; wrapper->stream_priv = stm_ctx->stream; stm_ctx->stream = wrapper; } ret = wrapper->open (wrapper, stm_ctx->stream_name); if (ret < 0) { dt_error (TAG, "stream open failed\n"); return -1; } dt_info (TAG, "stream open ok\n"); return 0; }
int dtvideo_stop (void *video_priv) { int ret; dtvideo_context_t *vctx = (dtvideo_context_t *) video_priv; if (!vctx) { dt_error (TAG, "[%s:%d] dt video context == NULL\n", __FUNCTION__, __LINE__); ret = -1; goto ERR0; } ret = video_stop (vctx); if (ret < 0) { dt_error (TAG, "[%s:%d] DTVIDEO STOP FAILED\n", __FUNCTION__, __LINE__); ret = -1; goto ERR0; } free (video_priv); video_priv = NULL; return ret; ERR0: return ret; }
int ffmpeg_adec_init(ad_wrapper_t *wrapper, void *parent) { wrapper->parent = parent; dtaudio_decoder_t *decoder = (dtaudio_decoder_t *)parent; //select video decoder and call init dt_info(TAG, "FFMPEG AUDIO DECODER INIT ENTER\n"); AVCodec *codec = NULL; if (decoder->decoder_priv) { avctxp = (AVCodecContext *) decoder->decoder_priv; } else { avctxp = alloc_ffmpeg_ctx(decoder); } if (!avctxp) { return -1; } enum AVCodecID id = avctxp->codec_id; dt_info(TAG, "[%s:%d] param-- src channel:%d sample:%d id:%d format:%d \n", __FUNCTION__, __LINE__, avctxp->channels, avctxp->sample_rate, id, decoder->para.afmt); dt_info(TAG, "[%s:%d] param-- dst channels:%d samplerate:%d \n", __FUNCTION__, __LINE__, decoder->para.dst_channels, decoder->para.dst_samplerate); codec = avcodec_find_decoder(id); if (NULL == codec) { dt_error(TAG, "[%s:%d] video codec find failed \n", __FUNCTION__, __LINE__); return -1; } if (avcodec_open2(avctxp, codec, NULL) < 0) { dt_error(TAG, "[%s:%d] video codec open failed \n", __FUNCTION__, __LINE__); return -1; } dt_info(TAG, "[%s:%d] ffmpeg dec init ok \n", __FUNCTION__, __LINE__); //alloc one frame for decode frame = av_frame_alloc(); return 0; }
static int create_cache_thread (cache_ctx_t * ctx) { pthread_t tid; ctx->cache_status = ST_STATUS_IDLE; ctx->cache_flag = ST_FLAG_NULL; int ret = pthread_create (&tid, NULL, (void *) &cache_thread, (void *)ctx); if (ret != 0) { dt_error (TAG "file:%s [%s:%d] data fill thread crate failed \n", __FILE__, __FUNCTION__, __LINE__); return -1; } ctx->cache_tid = tid; ctx->cache_status = ST_STATUS_RUNNING; dt_info (TAG, "cache Thread create ok\n"); return 0; }
int dt_add_event (event_t * event, event_server_t * server) { event_server_t *server_hub = server; if (!server_hub) { dt_error (TAG, "EVENT SEND FAILED \n"); return -1; } dt_lock (&server_hub->event_lock); if (server_hub->event_count == 0) server_hub->event = event; else { event_t *entry = server_hub->event; while (entry->next) entry = entry->next; entry->next = event; } server_hub->event_count++; dt_unlock (&server_hub->event_lock); return 0; }
static int ao_alsa_init(dtaudio_output_t *aout, dtaudio_para_t *para) { memcpy(&wrapper->para, para, sizeof(dtaudio_para_t)); snd_pcm_t *alsa_handle; snd_pcm_hw_params_t *alsa_hwparams; snd_pcm_sw_params_t *alsa_swparams; snd_pcm_uframes_t size; snd_pcm_uframes_t boundary; alsa_ctx_t *ctx = (alsa_ctx_t *)malloc(sizeof(*ctx)); if (!ctx) { return -1; } wrapper->ao_priv = ctx; int afmt = format_to_alsa(wrapper->para.bps); uint32_t channels = wrapper->para.dst_channels; uint32_t sr = wrapper->para.dst_samplerate; int bytes_per_sample = snd_pcm_format_physical_width(afmt) * channels / 8; int err = 0; err = snd_pcm_open(&alsa_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); free(ctx); wrapper->ao_priv = NULL; return -1; } snd_pcm_hw_params_alloca(&alsa_hwparams); snd_pcm_sw_params_alloca(&alsa_swparams); err = snd_pcm_hw_params_any(alsa_handle, alsa_hwparams); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_access(alsa_handle, alsa_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_format(alsa_handle, alsa_hwparams, afmt); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_channels_near(alsa_handle, alsa_hwparams, &channels); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_hwparams, &sr, NULL); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_hw_params(alsa_handle, alsa_hwparams); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } /****************************************************************** * Set HW Params Finish ******************************************************************/ /* buffer size means the entire size of alsa pcm buffer size*/ err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &size); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } ctx->buf_size = size * bytes_per_sample; /*period size means count processed every interrupt*/ err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &size, NULL); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } ctx->trunk_size = size * bytes_per_sample; dt_info(TAG, "outburst: %d, bytes_per_sample: %d, buffersize: %d\n", ctx->trunk_size, bytes_per_sample, ctx->buf_size); /****************************************************************** * set sw params ******************************************************************/ err = snd_pcm_sw_params_current(alsa_handle, alsa_swparams); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } #if SND_LIB_VERSION >= 0x000901 err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary); #else boundary = 0x7fffffff; #endif err = snd_pcm_sw_params_set_start_threshold(alsa_handle, alsa_swparams, size); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } err = snd_pcm_sw_params_set_stop_threshold(alsa_handle, alsa_swparams, boundary); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } #if SND_LIB_VERSION >= 0x000901 err = snd_pcm_sw_params_set_silence_size(alsa_handle, alsa_swparams, boundary); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } #endif err = snd_pcm_sw_params(alsa_handle, alsa_swparams); if (err < 0) { dt_error(TAG, "%s,%d: %s\n", __func__, __LINE__, snd_strerror(err)); return -1; } ctx->pause_support = snd_pcm_hw_params_can_pause(alsa_hwparams); //buf size limit ctx->buf_threshold = bytes_per_sample * sr * DEFAULT_TIME_SIZE / 1000; dt_info(TAG, "alsa audio init ok! outburst:%d thres:%d \n", ctx->trunk_size, ctx->buf_threshold); ctx->handle = alsa_handle; ctx->channels = wrapper->para.dst_channels; ctx->bps = wrapper->para.bps; ctx->samplerate = wrapper->para.dst_samplerate; return 0; }
static void *audio_decode_loop (void *arg) { int ret; dtaudio_decoder_t *decoder = (dtaudio_decoder_t *) arg; dtaudio_para_t *para = &decoder->aparam; dt_av_frame_t frame; ad_wrapper_t *wrapper = decoder->wrapper; dtaudio_context_t *actx = (dtaudio_context_t *) decoder->parent; dt_buffer_t *out = &actx->audio_decoded_buf; int declen, fill_size; //for some type audio, can not read completly frame uint8_t *frame_data = NULL; // point to frame start uint8_t *rest_data = NULL; int frame_size = 0; int rest_size = 0; int used; // used size after every decode ops adec_ctrl_t *pinfo = &decoder->info; memset(pinfo,0,sizeof(*pinfo)); pinfo->channels = para->channels; pinfo->samplerate = para->samplerate; pinfo->outptr = malloc(MAX_ONE_FRAME_OUT_SIZE); pinfo->outsize = MAX_ONE_FRAME_OUT_SIZE; dt_info (TAG, "[%s:%d] AUDIO DECODE START \n", __FUNCTION__, __LINE__); do { //maybe receive exit cmd in idle status, so exit prior to idle if (decoder->status == ADEC_STATUS_EXIT) { dt_debug (TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__); if (frame_data) free (frame_data); if (rest_data) free (rest_data); break; } if (decoder->status == ADEC_STATUS_IDLE) { dt_info (TAG, "[%s:%d] Idle status ,please wait \n", __FUNCTION__, __LINE__); usleep (100); continue; } /*read frame */ if (!decoder->parent) { usleep (10000); dt_info (TAG, "[%s:%d] decoder parent is NULL \n", __FUNCTION__, __LINE__); continue; } ret = audio_read_frame (decoder->parent, &frame); if (ret < 0 || frame.size <= 0) { usleep (1000); dt_debug (TAG, "[%s:%d] dtaudio decoder loop read frame failed \n", __FUNCTION__, __LINE__); continue; } //read ok,update current pts, clear the buffer size if (frame.pts >= 0) { if (decoder->pts_first == -1) { if(frame.pts == DT_NOPTS_VALUE) frame.pts = 0; decoder->pts_first = pts_exchange (decoder, frame.pts); dt_info (TAG, "first frame pts:%lld dts:%lld duration:%d size:%d\n", decoder->pts_first, frame.dts, frame.duration, frame.size); } decoder->pts_current = pts_exchange (decoder, frame.pts); dt_debug (TAG, "pkt pts:%lld current:%lld duration:%d pts_s:%lld dts:%lld buf_size:%d \n", frame.pts, decoder->pts_current, frame.duration, frame.pts / 90000, frame.dts, decoder->pts_buffer_size); decoder->pts_last_valid = decoder->pts_current; decoder->pts_buffer_size = 0; } //repack the frame if (frame_data) { free (frame_data); frame_data = NULL; frame_size = 0; } if (rest_size) frame_data = malloc (frame.size + rest_size); else frame_data = frame.data; if (!frame_data) { dt_error (TAG, "malloc audio frame failed ,we will lost one frame\n"); if (rest_data) free (rest_data); rest_size = 0; continue; } if (rest_size) // no rest data { dt_debug (TAG, "left %d byet last time\n", rest_size); memcpy (frame_data, rest_data, rest_size); free (rest_data); rest_data = NULL; memcpy (frame_data + rest_size, frame.data, frame.size); } frame_size = frame.size + rest_size; rest_size = 0; used = 0; declen = 0; pinfo->inptr = frame_data; pinfo->inlen = frame_size; pinfo->outlen = 0; //free pkt frame.data = NULL; frame.size = 0; DECODE_LOOP: if (decoder->status == ADEC_STATUS_EXIT) { dt_info (TAG, "[%s:%d] receive decode loop exit cmd \n", __FUNCTION__, __LINE__); if (frame_data) free (frame_data); break; } /*decode frame */ pinfo->consume = declen; used = wrapper->decode_frame (wrapper, pinfo); if (used < 0) { decoder->decode_err_cnt++; /* * if decoder is ffmpeg,do not restore data if decode failed * if decoder is not ffmpeg, restore raw stream packet if decode failed * */ if (!strcmp (wrapper->name, "ffmpeg audio decoder")) { dt_error (TAG, "[%s:%d] ffmpeg failed to decode this frame, just break\n", __FUNCTION__, __LINE__); decoder->decode_offset += pinfo->inlen; } continue; } else if (used == 0 && pinfo->outlen == 0) // used == 0 && out == 0 means need more data { //maybe need more data rest_data = malloc (pinfo->inlen); if (rest_data == NULL) { dt_error ("[%s:%d] rest_data malloc failed\n", __FUNCTION__, __LINE__); rest_size = 0; //skip this frame continue; } memcpy (rest_data, pinfo->inptr, pinfo->inlen); rest_size = pinfo->inlen; dt_info (TAG, "Maybe we need more data\n"); continue; } declen += used; pinfo->inlen -= used; decoder->decode_offset += used; decoder->pts_cache_size = pinfo->outlen; decoder->pts_buffer_size += pinfo->outlen; if (pinfo->outlen == 0) //get no data, maybe first time for init dt_info (TAG, "GET NO PCM DECODED OUT,used:%d \n",used); fill_size = 0; REFILL_BUFFER: if (decoder->status == ADEC_STATUS_EXIT) goto EXIT; /*write pcm */ if (buf_space (out) < pinfo->outlen) { dt_debug (TAG, "[%s:%d] output buffer do not left enough space ,space=%d level:%d outsie:%d \n", __FUNCTION__, __LINE__, buf_space (out), buf_level (out), pinfo->outlen); usleep (1000); goto REFILL_BUFFER; } ret = buf_put (out, pinfo->outptr + fill_size, pinfo->outlen); fill_size += ret; pinfo->outlen -= ret; decoder->pts_cache_size = pinfo->outlen; if (pinfo->outlen > 0) goto REFILL_BUFFER; if (pinfo->inlen) goto DECODE_LOOP; } while (1); EXIT: dt_info (TAG, "[file:%s][%s:%d]decoder loop thread exit ok\n", __FILE__, __FUNCTION__, __LINE__); /* free adec_ctrl_t buf */ if(pinfo->outptr) free(pinfo->outptr); pinfo->outlen = pinfo->outsize = 0; pthread_exit (NULL); return NULL; }