제목을 보고 좀 의하해할지도 모르겠다. 문서에서 말하는 해신은 즉, 스트림 서버에 저장되어 있는 스트림을 이야기한다. 물론 KBS(케이블)에서 들어오는 것을 TV 카드로 캡쳐받아서 스트림 서버에 저장해두었다. 지상파 스트림은 손쉽게 구할 수 있을 뿐더러, 쉽게 만들 수 있다.
현재 방송사들이 HD 의 송신비율을 높이고는 있지만, 아직도 많이 부족한 실정이다.
여기서 미리 알고 넘어가야할 것들이 있다. 바로 스트림 서버와 모듈레이터와 STB 와의 관계이다.

좀더 빠른 이해를 위해 그림을 보면서 설명하겠다. 앞에서 받은 해신(지상파 스트림)을 스트림 서버에 저장한다. 말이 스트림서버라 거창할지 모르지만, 일반 PC 라고 생각하면 된다. 이 서버에는 스트림 플레이어 라는 프로그램이 있다. 여기서는 PLAY RATE 를 세팅해준다.
맞춰주고 나서 PLAY 를 하면, 세팅해준 RATE 에 맞게 플레이 된다.

스트림은 스트림서버에 연결된 각각의 모듈레이터로 전달된다. 여기서는 모듈레이터에서 세팅된대로, Frecqucy 나 채널로 모듈화 시킨다.
현재 회사에는 QAM 모듈레이터와 VBS 모듈레이터가 있다. QAM 은 오픈케이블용이라고 보면 되고, VBS 는 지상파용 이라고 보면 된다.
각각의 모듈레이터에서 나온 스트림들은 컴바이너 라고 하는 장비에 들어간다. 이 것은 단순히 각각 따로인 QAM 스트림과 VSB 스트림을 한 데 합쳐주는 장비라고 보면 되겠다.

컴바이너로 부터 나온 스트림은 비로소 STB 튜너에 연결됨으로써 튜닝이 된다. 그리고나서 STB 출력단에 연결된 TV 로 전달된다. 결국 우리는 영상을 볼 수 있는 것이다. 앞으로 이런 점들을 염두해두기 바란다. 서론이 너무 길었던 것 같다.

해신을 보자!!

해신은 지상파 스트림이다. 그렇기 때문에 반드시 VSB 튜너가 장착된 타겟보드로 실행해야 한다. Ver2 보드는 모두 VSB 튜너가 장착되어 있다.
프로그램은 Server 에 있는 프로젝트 → 지상파 디렉토리의 최종버전을 가지고 테스트한다.

현재 최종버전의 소스는 공중파를 튜닝하기 위해 세팅된 소스다.
그렇기 때문에 그냥 실행하게 되면, 튜닝이 되지 않는다. 몇가지 수정을 해주어야 한다.
/src/nim/nimlib.c 의 소스파일을 보면, 약 268 라인을 보면, 아래와 같은 루틴이 나온다.
아래와 같이 주석을 풀어주고, 또는 주석을 처리해준다.

		case ATSC_AIR:
			if((1<chNum) && (chNum<70)) 	rfFreq = (T_Channel_Plan[chNum] + 17500) * 100;    // 주석을 푼다
			else return INVALID_PARAM;                                              // 주석을 푼다
/*     주석 처리 시작
			if(chPlan == HRC)
				{
				if(chNum == 1) rfFreq = 73750000;
				else if((2<chNum) && (chNum<5)) 		rfFreq = 55750000 + (chNum - 3) * 6000000;
				else if((4<chNum) && (chNum<7)) 		rfFreq = 77750000 + (chNum - 5) * 6000000;
				else if((6<chNum) && (chNum<14)) 	rfFreq = 175750000 + (chNum - 7) * 6000000;
				else if((13<chNum) && (chNum<23)) 	rfFreq = 121750000 + (chNum - 14) * 6000000;
				else if((22<chNum) && (chNum<95)) 	rfFreq = 217750000 + (chNum - 23) * 6000000;
				else if((94<chNum) && (chNum<100)) 	rfFreq = 91750000 + (chNum - 95) * 6000000;
				else if((99<chNum) && (chNum<158)) 	rfFreq = 649750000 + (chNum - 100) * 6000000;
				else return INVALID_PARAM;
				}
			else if((chPlan == IRC) || (chPlan == STD))
				{
				if(chPlan==IRC && chNum == 1) 		rfFreq = 75000000;
				else if((2<chNum) && (chNum<5)) 		rfFreq = 57000000 + (chNum - 3) * 6000000;
				else if((4<chNum) && (chNum<7)) 		rfFreq = 79000000 + (chNum - 5) * 6000000;
				else if((6<chNum) && (chNum<14))		rfFreq = 177000000 + (chNum - 7) * 6000000;
				else if((13<chNum) && (chNum<23)) 	rfFreq = 123000000 + (chNum - 14) * 6000000;
				else if((22<chNum) && (chNum<95)) 	rfFreq = 219000000 + (chNum - 23) * 6000000;
				else if((94<chNum) && (chNum<100)) 	rfFreq = 93000000 + (chNum - 95) * 6000000;
				else if((99<chNum) && (chNum<158)) 	rfFreq = 651000000 + (chNum - 100) * 6000000;
				else return INVALID_PARAM;
				} 
			else return INVALID_PARAM;	
  주석 처리 끝     */
			break;

이것으로 끝이 아니다. VSB 모듈레이터를 보면, 세팅된 값을 알 수 있는 데, 해신의 경우 ch 14 로 되어 있다. 때문에 소스 상에서 바로 채널 14 로 스캔함으로서 볼 수 있다. 이와 관련한 함수는 /src/cm/cmscan.c 에 있다.
약 68 라인에 보면 아래와 같은 루틴이 있다.

if (pStartEndCh == NULL)
		{
		switch(cmCheckCurrentBroadcastMode())
			{
			case TERRESTRIAL_MODE :
				startChannel = 14;		//pys_test    이곳을 수정한다.
				endChannel = 14;		//pys_test    역시 수정한다.
				break;
			case CABLE_MODE :
				startChannel = 102;		//pys_test
				endChannel = 103;		//pys_test
				break;
				}		
		}

위의 두 가지를 수정했다면, 이제 컴파일 후에 실행해보자!! 해신이 보일 것이다.

공중파 보기

이번에는 공중파를 보자!
서버에 올라가있는 최종 지상파 소스를 그대로 돌려도 상관이 없지만, 한번 살펴보고 넘어가자!! 역시 앞에 수정했던 2 군데를 아래와 같이 수정해주면 된다.

		case ATSC_AIR:
//			if((1<chNum) && (chNum<70)) 	rfFreq = (T_Channel_Plan[chNum] + 17500) * 100;
//			else return INVALID_PARAM;
 
			if(chPlan == HRC)
				{
				if(chNum == 1) rfFreq = 73750000;
				else if((2<chNum) && (chNum<5)) 		rfFreq = 55750000 + (chNum - 3) * 6000000;
				else if((4<chNum) && (chNum<7)) 		rfFreq = 77750000 + (chNum - 5) * 6000000;
				else if((6<chNum) && (chNum<14)) 	rfFreq = 175750000 + (chNum - 7) * 6000000;
				else if((13<chNum) && (chNum<23)) 	rfFreq = 121750000 + (chNum - 14) * 6000000;
				else if((22<chNum) && (chNum<95)) 	rfFreq = 217750000 + (chNum - 23) * 6000000;
				else if((94<chNum) && (chNum<100)) 	rfFreq = 91750000 + (chNum - 95) * 6000000;
				else if((99<chNum) && (chNum<158)) 	rfFreq = 649750000 + (chNum - 100) * 6000000;
				else return INVALID_PARAM;
				}
			else if((chPlan == IRC) || (chPlan == STD))
				{
				if(chPlan==IRC && chNum == 1) 		rfFreq = 75000000;
				else if((2<chNum) && (chNum<5)) 		rfFreq = 57000000 + (chNum - 3) * 6000000;
				else if((4<chNum) && (chNum<7)) 		rfFreq = 79000000 + (chNum - 5) * 6000000;
				else if((6<chNum) && (chNum<14))		rfFreq = 177000000 + (chNum - 7) * 6000000;
				else if((13<chNum) && (chNum<23)) 	rfFreq = 123000000 + (chNum - 14) * 6000000;
				else if((22<chNum) && (chNum<95)) 	rfFreq = 219000000 + (chNum - 23) * 6000000;
				else if((94<chNum) && (chNum<100)) 	rfFreq = 93000000 + (chNum - 95) * 6000000;
				else if((99<chNum) && (chNum<158)) 	rfFreq = 651000000 + (chNum - 100) * 6000000;
				else return INVALID_PARAM;
				} 
			else return INVALID_PARAM;	
 
			break;

이번에는 채널 스캔을 해주는 부분이다.

if (pStartEndCh == NULL)
		{
		switch(cmCheckCurrentBroadcastMode())
			{
			case TERRESTRIAL_MODE :
				startChannel = 82;		//pys_test    바로 이부분이다
				endChannel = 86;		//pys_test    바로 이부분이다
				break;
			case CABLE_MODE :
				startChannel = 102;		//pys_test
				endChannel = 103;		//pys_test
				break;
				}		
		}

마치면서

혹시라도 해신의 경우 채널 스캔이 안된다면, 테스트 모드로 들어가서, 주파수 입력을 '473' 으로 하고 스캔해보자!!

보너스!!

Ver2 타겟보드로 SD 스트림을 보도록 하자!!
현재 장착되어 있는 VSB 튜너가 SD 역시 지원하기 때문에, SD 스트림을 볼 수 있다. 프로그램을 약간 수정해주어야 한다.
소스 파일의 위치는 /src/cm/cmscan.c 이다.

/**************************************************************************
 DESCRIPTION:
 INPUT		: 
 OUTPUT		:
 RETURN		:
 ERRNO		: 
*/
void channelScan (U32 *pStartEndCh)
	{
	float			scannedChannel, scanCount, endChannel,startChannel,physicalNum;
	ARENA_RTN_t		errVal;
 
	autoScanInitial ();
 
	if (pStartEndCh == NULL)
		{
		startChannel = 103;		//pys_test
		endChannel = 103;		//pys_test
		}
	else
		{	
		startChannel = (float)((*pStartEndCh & 0xFFFF0000) >> 16);		
		endChannel = (float)(*pStartEndCh & 0xFFFF);		
		}
 
	for (physicalNum = startChannel; physicalNum <= endChannel; physicalNum++)
		{
		vchInitial (&scaningPch);
		scaningPch.NumInfo.physicalNum = physicalNum;
		scaningPch.NumInfo.chType = SOURCE_D_CABLE;	       <<<------  이 부분을 이렇게 수정!!!
 
		errVal = digitalTuneAndDBmake ();
		if (errVal == RTN_ABORT)
			goto SCAN_ABORT_JMP;
 
		scanCount++;
		scannedChannel = scanCount / (1 + endChannel - startChannel);
		percentOfScannedChannel = (scannedChannel * 100) - 1;
		ARENA_Print (("Percent of scanning = %d%%\n", percentOfScannedChannel));
		}
 
		autoScanComplete ();
    		ARENA_Print (("\nCM Message : Auto Scan Finished\n\n"));
 
		epgParsingEndNotifyToUi();    // scrambled stream인지 알 수 있는 시점,  모든 channel의 change 시마다 호출
 
		isAutoScanning = FALSE;
		semaphore_signal (pCmSemaId);
 
		// 원래 SCAN_COMPLETE는 반드시 성공하는 것을 의미 하지는 않으나, 여기서는 db가 만들어진 경우에만 complete메시지를 보낸다.
		// db가 없는데 complete 메시지를 받고 cmchange관련 함수들이 불려지면 안된다.
    		percentOfScannedChannel = DB_COMPLETE;
		if(vchPsipList.dbStatus == DB_COMPLETE)
		   	sendMsgToUI(SCAN_COMPLETE);
		else if(vchPsipList.dbStatus == DB_EMPTY)
			sendMsgToUI(SCAN_FAIL);
		return;
 
SCAN_ABORT_JMP:
    ARENA_Print (("\nCM MSG : Auto Scan Canceled, No Update\n\n"));
	cmVchListInitial (&vchPsipList);
//test_nvm					
	nvmCmInitialRead ();
 
	isAutoScanning = FALSE;
    semaphore_signal (pCmSemaId);
 
	vchInitial (&currentVch);
	cmPlayLastVch ();
return;
	}      

DAC5000 소스의 기본 설정으로는 air 로 되어 있지만, SD 스트림의 경우 QAM 이기 때문에 위와 같이 수정해주어야 한다. 입력은 SD 스트림이지만, output 에서 CBCR 이나 RGB 로 출력이 가능하다. 여기서 중요한 것은 채널 스캔의 가능 여부를 설정해주는 부분이라고 생각하면 되겠다.

  • computer/digitalarena/해신과_공중파_보기.txt
  • Last modified: 3 years ago
  • by likewind