Exemplo n.º 1
0
int parse_pat(CZapitChannel * const channel)
{
	CDemux dmx;
	
	/* buffer for program association table */
	unsigned char buffer[PAT_SIZE];

	/* current positon in buffer */
	unsigned short i;

	unsigned char filter[DMX_FILTER_SIZE];
	unsigned char mask[DMX_FILTER_SIZE];

	if (!channel)
		return -1;

	memset(filter, 0x00, DMX_FILTER_SIZE);
	memset(mask, 0x00, DMX_FILTER_SIZE);

	mask[0] = 0xFF;
	mask[4] = 0xFF;

	do {
		/* set filter for program association section */
		/* read section */
		if ((dmx.sectionFilter(0, filter, mask) < 0) || (dmx.read(buffer, PAT_SIZE) < 0))
			return -1;

		/* loop over service id / program map table pid pairs */
		for (i = 8; i < (((buffer[1] & 0x0F) << 8) | buffer[2]) + 3; i += 4) {
			/* compare service id */
			if (channel->getServiceId() == ((buffer[i] << 8) | buffer[i+1])) {
				/* store program map table pid */
				channel->setPmtPid(((buffer[i+2] & 0x1F) << 8) | buffer[i+3]);
				return 0;
			}
		}
	} while (filter[4]++ != buffer[7]);

	return -1;
}
Exemplo n.º 2
0
int parse_nit(const t_satellite_position satellite_position, const unsigned char DiSEqC)
{
	CDemux dmx;

	unsigned char buffer[NIT_SIZE];

	/* position in buffer */
	unsigned short pos;
	unsigned short pos2;

	/* network_information_section elements */
	unsigned short section_length;
	unsigned short network_descriptors_length;
	unsigned short transport_descriptors_length;
	unsigned short transport_stream_loop_length;
	t_transport_stream_id transport_stream_id;
	t_original_network_id original_network_id;
//	unsigned short network_id;

	transponder_id_t transponder_id;

	unsigned char filter[DMX_FILTER_SIZE];
	unsigned char mask[DMX_FILTER_SIZE];

	memset(filter, 0x00, DMX_FILTER_SIZE);
	memset(mask, 0x00, DMX_FILTER_SIZE);

	filter[0] = 0x40;
	filter[4] = 0x00;
	mask[0] = 0xFF;
	mask[4] = 0xFF;

	do {
		if ((dmx.sectionFilter(0x10, filter, mask) < 0) || (dmx.read(buffer, NIT_SIZE) < 0))
			return -1;

		section_length = ((buffer[1] & 0x0F) << 8) + buffer[2];
//		network_id = ((buffer[3] << 8)| buffer [4]);
		network_descriptors_length = ((buffer[8] & 0x0F) << 8) | buffer[9];

		for (pos = 10; pos < network_descriptors_length + 10; pos += buffer[pos + 1] + 2)
		{
			switch (buffer[pos])
			{
/*			case 0x0F:
				Private_data_indicator_descriptor(buffer + pos);
				break;
*/
			case 0x40:
				network_name_descriptor(buffer + pos);
				break;

			case 0x4A:
				linkage_descriptor(buffer + pos);
				break;

			case 0x5B:
				multilingual_network_name_descriptor(buffer + pos);
				break;

/*			case 0x5F:
				private_data_specifier_descriptor(buffer + pos);
				break;
*/
			case 0x80: /* unknown, Eutelsat 13.0E */
				break;

			case 0x90: /* unknown, Eutelsat 13.0E */
				break;

			default:
				DBG("first_descriptor_tag: %02x", buffer[pos]);
				break;
			}
		}

		transport_stream_loop_length = ((buffer[pos] & 0x0F) << 8) | buffer[pos + 1];

		if (!transport_stream_loop_length)
			continue;

		for (pos += 2; pos < section_length - 3; pos += transport_descriptors_length + 6)
		{
			transport_stream_id = (buffer[pos] << 8) | buffer[pos + 1];
			original_network_id = (buffer[pos + 2] << 8) | buffer[pos + 3];
			transport_descriptors_length = ((buffer[pos + 4] & 0x0F) << 8) | buffer[pos + 5];

			// frequency will be inserted in satellite/cable_delivery_system_descriptor()
			transponder_id = CREATE_TRANSPONDER_ID_FROM_FREQUENCY_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID(0, satellite_position,original_network_id,transport_stream_id);

			if (transponders.find(transponder_id) == transponders.end())
			{
				for (pos2 = pos + 6; pos2 < pos + transport_descriptors_length + 6; pos2 += buffer[pos2 + 1] + 2)
				{
					switch (buffer[pos2])
					{
					case 0x41:
						service_list_descriptor(buffer + pos2, transport_stream_id, original_network_id);
						break;

					case 0x42:
						stuffing_descriptor(buffer + pos2);
						break;

					case 0x43:
						if (satellite_delivery_system_descriptor(buffer + pos2, transponder_id, DiSEqC) < 0)
							return -2;
						break;

					case 0x44:
						if (cable_delivery_system_descriptor(buffer + pos2, transponder_id) < 0)
							return -2;
						break;

					case 0x5A:
						if (terrestrial_delivery_system_descriptor(buffer + pos2) < 0)
							return -2;
						break;

					case 0x5F:
						private_data_specifier_descriptor(buffer + pos2);
						break;

					case 0x62:
						frequency_list_descriptor(buffer + pos2);
						break;

					case 0x82: /* unknown, Eutelsat 13.0E */
						break;

					default:
						DBG("second_descriptor_tag: %02x", buffer[pos2]);
						break;
					}
				}
			}
		}
	} while (filter[4]++ != buffer[7]);

	return 0;
}
Exemplo n.º 3
0
void CVideoDecoder::ThreadEntry ()
{
    CDemux* pDemux 					= mpDemux;
    AVStream* pStream 				= mpStream;
    CVideoStubRender* pVStubRender 	= (CVideoStubRender*)mpStubRender;
    CMasterClock* pClock 			= mpClock;
    int Ret 						= ERR_NONE;
    int bFrameFinished				= 0;
    AVCodecContext *pCodecContext	= NULL;
    AVPacket AVPkt;
    int64_t  PTS;

    if (pDemux == NULL || pStream == NULL || pVStubRender == NULL || pStream->codec == NULL)
    {
        ERROR ("mpDecoder || mpStream || mpStubRender || mpStream->codec== NULL!");
        return;
    }
    pCodecContext = pStream->codec;

    memset((void*)&AVPkt,0,sizeof(AVPacket));

    DEBUG ("start video decoder loop!");

    for(;;)
    {
        if(mbQuit)
        {
            INFO("mbQuit");
            PlayCore::GetInstance()->avcodec_flush_buffers(pCodecContext);
            break;
        }

        if(pDemux->GetSyncPTS()>=0.0)//已经设定了SyncPTS
        {
            if(!pDemux->IsSynced())//没有被音频流Sync
            {
                DEBUG("NO FOUND SYNCED !!");
                usleep(25*1000);
                continue;
            }
            else if(!pClock->IsRun())//已经设定SyncPTs并且被其他流sync并且当前状态不是播放状态
            {
                usleep(1*1000);//Reduce CPU usage
                continue;
            }
        }
        else
        {
            DEBUG("TRY SHOW FIRST KEY VIDEO FRAME mbFirstKeyFrame %s",mbFirstKeyFrame?"true":"false");
        }

        if(mbNextFrame)
        {
            AVPkt = pDemux->GetVideoPacket ();
            if (AVPkt.data == 0 || AVPkt.size == 0)
            {
                INFO ("get NULL packet! continue! must be end of pStream!!! stop thread!");
                break;
            }

            //如果A/V已经同步,但此时视频时间戳严重落后于系统时钟
            if(pDemux->IsSynced()&&mbNeedReSync)
            {
                double CurClock = pClock->GetCurrentClock ();
                double FramePTS = AVPkt.pts * av_q2d (pStream->time_base);
                double Diff = FramePTS - CurClock;
                DEBUG ("V:SyncOut CurClock=%f, FramePTS=%f, Diff=%f", CurClock, FramePTS, Diff);

                if (Diff >= CMasterClock::AVThresholdSync)
                {
                    DEBUG ("V:Sync CurClock=%f, FramePTS=%f, Diff=%f", CurClock, FramePTS, Diff);
                }
                else
                {
                    PlayCore::GetInstance()->av_free_packet (&AVPkt);
                    memset((void*)&AVPkt,0,sizeof(AVPacket));
                    continue;
                }

            }

            int len = CVideoDecoderImp::Decode (pCodecContext, mpFrame, &bFrameFinished, &AVPkt, &PTS);

            if (len < 0 || bFrameFinished == 0)
            {
                WARN ("CVideoDecoderImp::Decode fail! continue to next packet!");
                PlayCore::GetInstance()->av_free_packet (&AVPkt);
                memset((void*)&AVPkt,0,sizeof(AVPacket));
                continue;
            }

            DEBUG("mbFirstKeyFrame %d,key_frame %d,pict_type %d mbNeedReSync %d AV_PICTURE_TYPE_I %d",mbFirstKeyFrame,mpFrame->key_frame,mpFrame->pict_type,mbNeedReSync,AV_PICTURE_TYPE_I);
            //需要关键帧
            if(!pDemux->IsSynced())
            {
                //不是关键帧continue
                if(!(mpFrame->key_frame && mpFrame->pict_type == AV_PICTURE_TYPE_I))
                {
                    DEBUG("Not Key frame continue");
                    PlayCore::GetInstance()->av_free_packet (&AVPkt);
                    memset((void*)&AVPkt,0,sizeof(AVPacket));
                    continue;
                }
                else //第一次音视频Sync
                {
                    INFO("First Sync after opened");
                    mbFirstKeyFrame = true;
                }

            }
            else if(mbNeedReSync) //视频时间戳严重落后于系统时钟,第一个合适的关键帧
            {
                if(!(mpFrame->key_frame && mpFrame->pict_type == AV_PICTURE_TYPE_I))
                {
                    DEBUG("Not Key frame continue");
                    PlayCore::GetInstance()->av_free_packet (&AVPkt);
                    memset((void*)&AVPkt,0,sizeof(AVPacket));
                    continue;
                }
                else
                {
                    INFO("mbNeedReSync %d",mbNeedReSync);
                    mbNeedReSync 	= false;
                    mbFirstKeyFrame = false;
                }
            }
            else//pDemux go on
            {
                mbFirstKeyFrame = false;
            }
        }
        if (pClock)
        {
            double FramePTS = PTS * av_q2d (pStream->time_base);
            //渲染视频首个关键帧并且不是播放过程中视频解码落后于系统时钟。设定音频同步时间点
            if(mbFirstKeyFrame)
            {
                Ret = pVStubRender->ShowPicture (mpFrame);

                INFO("IS Key frame mbFirstKeyFrame %d FramePTS %f ShowPicture Ret %d",mbFirstKeyFrame,FramePTS,Ret);

                //成功渲染视频
                if(Ret>=0 || Ret == ERR_DEVICE_NOSET)
                {
                    //得到同步时间点,
                    double SyncPTS = pDemux->GetSyncPTS();
                    INFO("pDemux->GetSyncPTS() %f",SyncPTS);
                    if(SyncPTS<0.0)
                    {
                        //设定同步时间点
                        pDemux->SetSyncPTS(FramePTS);
                        //设定时钟的起始时间点
                        pClock->SetOriginClock (FramePTS);

                        //surface fixed
                        pVStubRender->ShowPicture (mpFrame);

                        //如果没有音频数据流设定为Synced;
                        if(pDemux->GetAudioStreamIndex()<0)
                        {
                            pDemux->SetSynced(true);
                        }

                        mbFirstKeyFrame = false;
                        mbNextFrame = true;
                    }
                }
            }
            else
            {
                double CurClock = pClock->GetCurrentClock ();
                double Diff = FramePTS - CurClock;

                DEBUG ("V:CurClock=%f, FramePTS=%f, Diff=%f", CurClock, FramePTS, Diff);

                if (fabs(Diff) < CMasterClock::AVThresholdNoSync)
                {
                    mbNextFrame = true;

                    if (Diff <= 0)
                    {
                        VERBOSE ("show it at once.");
                    }
                    else
                    {
                        unsigned int usec = Diff * 1000 * 1000;
                        VERBOSE ("wait %d usec", usec);
                        usleep (usec);
                    }

                    Ret = pVStubRender->ShowPicture (mpFrame);
                }
                else
                {
                    if (Diff < 0)
                    {
                        mbNextFrame = true;

                        //如果系统时钟是以视频时钟为基准的,调整系统时钟
                        if(pClock->GetClockType()==CMasterClock::CLOCK_VIDEO)
                        {
                            WARN("we reset master timer to video FramePTS");
                            double ClockTime = PlayCore::GetInstance()->av_gettime() / 1000000.0;
                            pClock->SetOriginClock (FramePTS, ClockTime);
                            Ret = pVStubRender->ShowPicture (mpFrame);
                        }
                        else//否则是以其他(音频,系统时间)为系统时钟,此时视频严重落后于同步的时间范围值,
                        {   //对于直播不需要设定需要查找最近的关键帧标识

                            DEBUG("we need ReSync video FramePTS Diff %f",Diff);
                        }
                    }
                    else
                    {
                        WARN ("video FramePTS far early than curr_pts Diff %f",Diff);
                        unsigned int usec = Diff * 1000 * 1000;
                        mbNextFrame  = false;
                        usleep (1*1000);
                    }
                }
                DEBUG("ShowPicture Ret %d",Ret);
            }
        }
        else
        {
            ERROR ("you have not set Master Clock!!! will not show pictures!");
        }

        PlayCore::GetInstance()->av_free_packet (&AVPkt);
        memset((void*)&AVPkt,0,sizeof(AVPacket));
    }

    Reset();

    if (AVPkt.data != 0)
    {
        PlayCore::GetInstance()->av_free_packet (&AVPkt);
    }
    DEBUG ("end of video out thread!");
}