// 函数实现 void* playeropen(char *file, void *extra) { PLAYER *player = NULL; AVCodec *decoder = NULL; int vformat = 0; int width = 0; int height = 0; uint64_t alayout = 0; int aformat = 0; int arate = 0; uint32_t i = 0; // init log // log_init(TEXT("DEBUGER")); // av register all av_register_all(); // alloc player context player = (PLAYER*)malloc(sizeof(PLAYER)); memset(player, 0, sizeof(PLAYER)); // create packet queue pktqueue_create(&(player->PacketQueue)); // open input file if (avformat_open_input(&(player->pAVFormatContext), file, NULL, 0) != 0) { goto error_handler; } // find stream info if (avformat_find_stream_info(player->pAVFormatContext, NULL) < 0) { goto error_handler; } // get video & audio codec context player->iAudioStreamIndex = -1; player->iVideoStreamIndex = -1; for (i=0; i<player->pAVFormatContext->nb_streams; i++) { switch (player->pAVFormatContext->streams[i]->codec->codec_type) { case AVMEDIA_TYPE_AUDIO: player->iAudioStreamIndex = i; player->pAudioCodecContext = player->pAVFormatContext->streams[i]->codec; player->dAudioTimeBase = av_q2d(player->pAVFormatContext->streams[i]->time_base) * 1000; break; case AVMEDIA_TYPE_VIDEO: player->iVideoStreamIndex = i; player->pVideoCodecContext = player->pAVFormatContext->streams[i]->codec; player->dVideoTimeBase = av_q2d(player->pAVFormatContext->streams[i]->time_base) * 1000; player->tVideoFrameRate = player->pAVFormatContext->streams[i]->r_frame_rate; if (player->tVideoFrameRate.num / player->tVideoFrameRate.den > 100) { player->tVideoFrameRate.num = 30; player->tVideoFrameRate.den = 1; } break; } } // open audio codec if (player->iAudioStreamIndex != -1) { decoder = avcodec_find_decoder(player->pAudioCodecContext->codec_id); if (!decoder || avcodec_open(player->pAudioCodecContext, decoder, NULL) < 0) { log_printf(TEXT("failed to find or open decoder for audio !\n")); player->iAudioStreamIndex = -1; } } // open video codec if (player->iVideoStreamIndex != -1) { decoder = avcodec_find_decoder(player->pVideoCodecContext->codec_id); if (!decoder || avcodec_open(player->pVideoCodecContext, decoder, NULL) < 0) { log_printf(TEXT("failed to find or open decoder for video !\n")); player->iVideoStreamIndex = -1; } } // for video if (player->iVideoStreamIndex != -1) { vformat = player->pVideoCodecContext->pix_fmt; width = player->pVideoCodecContext->width; height = player->pVideoCodecContext->height; } // for audio if (player->iAudioStreamIndex != -1) { alayout = player->pAudioCodecContext->channel_layout; //++ fix audio channel layout issue if (alayout == 0) { alayout = av_get_default_channel_layout(player->pAudioCodecContext->channels); } //-- fix audio channel layout issue aformat = player->pAudioCodecContext->sample_fmt; arate = player->pAudioCodecContext->sample_rate; } // open core render player->hCoreRender = renderopen(extra, player->tVideoFrameRate, vformat, width, height, arate, (AVSampleFormat)aformat, alayout); // make sure player status paused player->nPlayerStatus = 0xf; pthread_create(&(player->hAVDemuxThread), NULL, AVDemuxThreadProc , player); pthread_create(&(player->hADecodeThread), NULL, AudioDecodeThreadProc, player); pthread_create(&(player->hVDecodeThread), NULL, VideoDecodeThreadProc, player); return player; error_handler: playerclose(player); return NULL; }
int streamxmit_init(STREAM_RTP_DEST_T *pDest, const STREAM_DEST_CFG_T *pDestCfg) { unsigned int numPkts = 0; unsigned int szPkt; int iTmp; STREAM_XMIT_QUEUE_T *pAsyncQ = NULL; PKTQUEUE_T *pQ = NULL; STREAM_STATS_MONITOR_T *pMonitor = NULL; if(!pDest || !pDestCfg) { return -1; } pAsyncQ = &pDest->asyncQ; if(pDestCfg->pFbReq && pDestCfg->pFbReq->nackRtpRetransmit) { pAsyncQ->doRtcpNack = 1; } pAsyncQ->doAsyncXmit = 0; // TODO: implement for packet output smoothing // // We run if we are to do async RTP xmit // or we support RTP-retransmissions for video (using RTCP NACK notifications) // if(!pAsyncQ->doAsyncXmit && (!pAsyncQ->doRtcpNack || pDest->pRtpMulti->isaud)) { return 0; } if(pAsyncQ->doRtcpNack) { // // Compute an RTP retransmission queue size // if(pDest->pRtpMulti->pStreamerCfg->xcode.vid.common.cfgDo_xcode && pDest->pRtpMulti->pStreamerCfg->xcode.vid.out[pDestCfg->xcodeOutidx].cfgBitRateOut > 0 && pDest->pRtpMulti->init.maxPayloadSz > 0) { iTmp = (pDest->pRtpMulti->pStreamerCfg->xcode.vid.out[pDestCfg->xcodeOutidx].cfgBitRateOut / (8 * 10 * pDest->pRtpMulti->init.maxPayloadSz) + 2) * 10; numPkts = MIN(150, MAX(50, iTmp)); } else { numPkts = 100; } //TODO: really only need burstmeter when capping retransmission traffic burstmeter_init(&pAsyncQ->retransmissionMeter, 1, 1000); //pAsyncQ->retransmissionKbpsMax = 30; } else { numPkts = 40; } szPkt = pDest->pRtpMulti->init.maxPayloadSz + RTP_HEADER_LEN + DTLS_OVERHEAD_SIZE + 64; // No locking!... should rely on pAsyncQ->mtx if(!(pQ = pktqueue_create(numPkts, szPkt, 0, 0, 0, sizeof(STREAMXMIT_PKT_HDR_T), 0, 1))) { return -1; } LOG(X_DEBUG("Created RTP %soutput packet queue size: %dB x %dpkts"), pAsyncQ->doRtcpNack ? "NACK " : "", szPkt, numPkts); pQ->cfg.overwriteType = PKTQ_OVERWRITE_OK; pQ->cfg.id = STREAMER_QID_NACK; pktqueue_setrdr(pQ, 0); pthread_mutex_init(&pAsyncQ->mtx, NULL); pAsyncQ->nackHistoryMs = RTP_RETRANSMIT_HISTORY_MS; pAsyncQ->pQ = pQ; // // Start the RTP output queue processor thread // if(pDestCfg->pMonitor && pDestCfg->pMonitor->active) { pMonitor = pDestCfg->pMonitor; } streamxmit_async_start(pDest->pRtpMulti, pMonitor, 0); return 0; }