view recpt1/test.c @ 0:67e8eca28a80

initial import
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 16 Feb 2009 15:41:49 +0900
parents
children
line wrap: on
line source

#include	<stdio.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<fcntl.h>
#include	<time.h>
#include	<stdlib.h>
#include	<string.h>
#include	<pthread.h>
#include        <unistd.h>

#include	<sys/ioctl.h>
#include	"pt1_ioctl.h"

char	*bsdev[2] = {
	"/dev/pt1video1",
	"/dev/pt1video0"
};
char	*isdb_t_dev[2] = {
	"/dev/pt1video2",
	"/dev/pt1video3"
};

#define		CHTYPE_SATELLITE		0		// 衛星デジタル放送
#define		CHTYPE_GROUND			1		// 地上デジタル放送
#define		MAX_QUEUE				8192

#define		MAX_READ_SIZE	(1024 * 16)
#define		WRITE_SIZE		(1024 * 1024 * 2)
#define		TRUE	1
#define		FALSE	0

typedef	struct	_BUFSZ{
	int		size ;
	u_char	buffer[MAX_READ_SIZE];
}BUFSZ;

typedef	struct	_QUEUE_T{
	unsigned	int		in;			// 次に入れるインデックス
	unsigned	int		out;		// 次に出すインデックス
	unsigned	int		size;		// キューのサイズ
	unsigned	int		no_full;	// 満タンになると 0 になる
	unsigned	int		no_empty;	// 空っぽになると 0 になる
	pthread_mutex_t	mutex;
	pthread_cond_t	cond_full;		// データが満タンのときに待つための cond
	pthread_cond_t	cond_empty;		// データが空のときに待つための cond
	BUFSZ			*buffer[1];			// バッファポインタ
}QUEUE_T;

int		wfd;		// ファイル書き込み用
int		f_exit = FALSE ;

typedef	struct	_ISDB_T_FREQ_CONV_TABLE {
	int		set_freq ;				// 実際にioctl()を行う値
	int		type ;					// チャンネルタイプ
	int		add_freq ;				// 追加する周波数(BS/CSの場合はスロット番号)
	char	*parm_freq ;			// パラメータで受ける値
}ISDB_T_FREQ_CONV_TABLE;

// 変換テーブル(ISDB-T用)
#define		MAX_CHANNEL_SELECT		123
// 実際にioctl()を行う値の部分はREADMEを参照の事。
// BS/CSの設定値およびスロット番号は
// http://www5e.biglobe.ne.jp/~kazu_f/digital-sat/index.htmlより取得。
//

ISDB_T_FREQ_CONV_TABLE	isdb_t_conv_table[MAX_CHANNEL_SELECT] = {
	{   0, CHTYPE_SATELLITE, 0, "151"},	// 151ch:BS朝日
	{   0, CHTYPE_SATELLITE, 1, "161"},	// 161ch:BS-i
	{   1, CHTYPE_SATELLITE, 1, "171"},	// 171ch:BSジャパン
	{   4, CHTYPE_SATELLITE, 0, "211"},	// 211ch:BS11デジタル
	{   4, CHTYPE_SATELLITE, 2, "222"},	// 222ch:TwellV
	{   6, CHTYPE_SATELLITE, 0, "141"},	// 141ch:BS日テレ
	{   6, CHTYPE_SATELLITE, 1, "181"},	// 181ch:BSフジ
	{   7, CHTYPE_SATELLITE, 0, "101"},	// 101ch:NHK衛星第1放送(BS1)
	{   7, CHTYPE_SATELLITE, 0, "102"},	// 102ch:NHK衛星第2放送(BS2)
	{   7, CHTYPE_SATELLITE, 1, "103"}, // 103ch:NHKハイビジョン(BShi)
	{   0, CHTYPE_GROUND, 0,   "1"}, {   1, CHTYPE_GROUND, 0,   "2"},
	{   2, CHTYPE_GROUND, 0,   "3"}, {   3, CHTYPE_GROUND, 0, "C13"},
	{   4, CHTYPE_GROUND, 0, "C14"}, {   5, CHTYPE_GROUND, 0, "C15"},
	{   6, CHTYPE_GROUND, 0, "C16"}, {   7, CHTYPE_GROUND, 0, "C17"},
	{   8, CHTYPE_GROUND, 0, "C18"}, {   9, CHTYPE_GROUND, 0, "C19"},
	{  10, CHTYPE_GROUND, 0, "C20"}, {  11, CHTYPE_GROUND, 0, "C21"},
	{  12, CHTYPE_GROUND, 0, "C22"}, {  13, CHTYPE_GROUND, 0,   "4"},
	{  14, CHTYPE_GROUND, 0,   "5"}, {  15, CHTYPE_GROUND, 0,   "6"},
	{  16, CHTYPE_GROUND, 0,   "7"}, {  17, CHTYPE_GROUND, 0,   "8"},
	{  18, CHTYPE_GROUND, 0,   "9"}, {  19, CHTYPE_GROUND, 0,  "10"},
	{  20, CHTYPE_GROUND, 0,  "11"}, {  21, CHTYPE_GROUND, 0,  "12"},
	{  22, CHTYPE_GROUND, 0, "C23"}, {  23, CHTYPE_GROUND, 0, "C24"},
	{  24, CHTYPE_GROUND, 0, "C25"}, {  25, CHTYPE_GROUND, 0, "C26"},
	{  26, CHTYPE_GROUND, 0, "C27"}, {  27, CHTYPE_GROUND, 0, "C28"},
	{  28, CHTYPE_GROUND, 0, "C29"}, {  29, CHTYPE_GROUND, 0, "C30"},
	{  30, CHTYPE_GROUND, 0, "C31"}, {  31, CHTYPE_GROUND, 0, "C32"},
	{  32, CHTYPE_GROUND, 0, "C33"}, {  33, CHTYPE_GROUND, 0, "C34"},
	{  34, CHTYPE_GROUND, 0, "C35"}, {  35, CHTYPE_GROUND, 0, "C36"},
	{  36, CHTYPE_GROUND, 0, "C37"}, {  37, CHTYPE_GROUND, 0, "C38"},
	{  38, CHTYPE_GROUND, 0, "C39"}, {  39, CHTYPE_GROUND, 0, "C40"},
	{  40, CHTYPE_GROUND, 0, "C41"}, {  41, CHTYPE_GROUND, 0, "C42"},
	{  42, CHTYPE_GROUND, 0, "C43"}, {  43, CHTYPE_GROUND, 0, "C44"},
	{  44, CHTYPE_GROUND, 0, "C45"}, {  45, CHTYPE_GROUND, 0, "C46"},
	{  46, CHTYPE_GROUND, 0, "C47"}, {  47, CHTYPE_GROUND, 0, "C48"},
	{  48, CHTYPE_GROUND, 0, "C49"}, {  49, CHTYPE_GROUND, 0, "C50"},
	{  50, CHTYPE_GROUND, 0, "C51"}, {  51, CHTYPE_GROUND, 0, "C52"},
	{  52, CHTYPE_GROUND, 0, "C53"}, {  53, CHTYPE_GROUND, 0, "C54"},
	{  54, CHTYPE_GROUND, 0, "C55"}, {  55, CHTYPE_GROUND, 0, "C56"},
	{  56, CHTYPE_GROUND, 0, "C57"}, {  57, CHTYPE_GROUND, 0, "C58"},
	{  58, CHTYPE_GROUND, 0, "C59"}, {  59, CHTYPE_GROUND, 0, "C60"},
	{  60, CHTYPE_GROUND, 0, "C61"}, {  61, CHTYPE_GROUND, 0, "C62"},
	{  62, CHTYPE_GROUND, 0, "C63"}, {  63, CHTYPE_GROUND, 0,  "13"},
	{  64, CHTYPE_GROUND, 0,  "14"}, {  65, CHTYPE_GROUND, 0,  "15"},
	{  66, CHTYPE_GROUND, 0,  "16"}, {  67, CHTYPE_GROUND, 0,  "17"},
	{  68, CHTYPE_GROUND, 0,  "18"}, {  69, CHTYPE_GROUND, 0,  "19"},
	{  70, CHTYPE_GROUND, 0,  "20"}, {  71, CHTYPE_GROUND, 0,  "21"},
	{  72, CHTYPE_GROUND, 0,  "22"}, {  73, CHTYPE_GROUND, 0,  "23"},
	{  74, CHTYPE_GROUND, 0,  "24"}, {  75, CHTYPE_GROUND, 0,  "25"},
	{  76, CHTYPE_GROUND, 0,  "26"}, {  77, CHTYPE_GROUND, 0,  "27"},
	{  78, CHTYPE_GROUND, 0,  "28"}, {  79, CHTYPE_GROUND, 0,  "29"},
	{  80, CHTYPE_GROUND, 0,  "30"}, {  81, CHTYPE_GROUND, 0,  "31"},
	{  82, CHTYPE_GROUND, 0,  "32"}, {  83, CHTYPE_GROUND, 0,  "33"},
	{  84, CHTYPE_GROUND, 0,  "34"}, {  85, CHTYPE_GROUND, 0,  "35"},
	{  86, CHTYPE_GROUND, 0,  "36"}, {  87, CHTYPE_GROUND, 0,  "37"},
	{  88, CHTYPE_GROUND, 0,  "38"}, {  89, CHTYPE_GROUND, 0,  "39"},
	{  90, CHTYPE_GROUND, 0,  "40"}, {  91, CHTYPE_GROUND, 0,  "41"},
	{  92, CHTYPE_GROUND, 0,  "42"}, {  93, CHTYPE_GROUND, 0,  "43"},
	{  94, CHTYPE_GROUND, 0,  "44"}, {  95, CHTYPE_GROUND, 0,  "45"},
	{  96, CHTYPE_GROUND, 0,  "46"}, {  97, CHTYPE_GROUND, 0,  "47"},
	{  98, CHTYPE_GROUND, 0,  "48"}, {  99, CHTYPE_GROUND, 0,  "49"},
	{ 100, CHTYPE_GROUND, 0,  "50"}, { 101, CHTYPE_GROUND, 0,  "51"},
	{ 102, CHTYPE_GROUND, 0,  "52"}, { 103, CHTYPE_GROUND, 0,  "53"},
	{ 104, CHTYPE_GROUND, 0,  "54"}, { 105, CHTYPE_GROUND, 0,  "55"},
	{ 106, CHTYPE_GROUND, 0,  "56"}, { 107, CHTYPE_GROUND, 0,  "57"},
	{ 108, CHTYPE_GROUND, 0,  "58"}, { 109, CHTYPE_GROUND, 0,  "59"},
	{ 110, CHTYPE_GROUND, 0,  "60"}, { 111, CHTYPE_GROUND, 0,  "61"},
	{ 112, CHTYPE_GROUND, 0,  "62"}
};

// 周波数テーブル変換
ISDB_T_FREQ_CONV_TABLE	*searchrecoff(char *channel)
{
	int		lp ;

	for(lp = 0 ; lp < 113 ; lp++){
		// 文字列&長さ一致したら周波数テーブル番号を返却する
		if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, strlen(channel)) == 0) &&
			(strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))){
			return &isdb_t_conv_table[lp] ;
		}
	}
	return NULL ;
}

QUEUE_T*	create_queue(size_t size)
{
	QUEUE_T*	p_queue;
	int		memsize = sizeof(QUEUE_T) + (size * sizeof(BUFSZ));

	p_queue = (QUEUE_T*)calloc(memsize, sizeof(char));

	if(p_queue != NULL){
		p_queue->size = size;
		p_queue->no_full = size;
		p_queue->no_empty = 0;
		pthread_mutex_init(&p_queue->mutex, NULL);
		pthread_cond_init(&p_queue->cond_full, NULL);
		pthread_cond_init(&p_queue->cond_empty, NULL);
	}

	return p_queue;
}

void	destroy_queue(QUEUE_T *p_queue)
{
	if(p_queue != NULL){
		pthread_mutex_destroy(&p_queue->mutex);
		pthread_cond_destroy(&p_queue->cond_full);
		pthread_cond_destroy(&p_queue->cond_empty);
		free(p_queue);
	}
}

// 関数名: enqueue
//  キューにデータを入れる
//  データが満タンな場合は、ブロックします
void	enqueue(QUEUE_T *p_queue, BUFSZ *data)
{
	pthread_mutex_lock(&p_queue->mutex);
	// -- ここから、クリティカルセクション --

	// 満タンじゃなくなるまで待つ
	while(!p_queue->no_full) {
		pthread_cond_wait(&p_queue->cond_full, &p_queue->mutex);
		printf("Full\n");
	}

	p_queue->buffer[p_queue->in] = data;

	p_queue->in++;
	p_queue->in %= p_queue->size;

	p_queue->no_full--;
	p_queue->no_empty++;

	pthread_mutex_unlock(&p_queue->mutex);
	pthread_cond_signal(&p_queue->cond_empty);
}

// 関数名: dequeue
//  キューにデータを入れる
//  データが満タンな場合は、ブロックします
BUFSZ	*dequeue(QUEUE_T *p_queue)
{
	void	*result;

	pthread_mutex_lock(&p_queue->mutex);
	// -- ここから、クリティカルセクション --

	// 空っぽじゃなくなるまで待つ
	while (!p_queue->no_empty) {
		pthread_cond_wait(&p_queue->cond_empty, &p_queue->mutex);
	}

	// データを取り出す
	result = p_queue->buffer[p_queue->out];

	// 次にデータを取り出す場所をインクリメント
	p_queue->out++;
	p_queue->out %= p_queue->size;

	// フラグの更新
	p_queue->no_full++;
	p_queue->no_empty--;

	// -- ここまで、クリティカルセクション --
	pthread_mutex_unlock(&p_queue->mutex);
	pthread_cond_signal(&p_queue->cond_full);

	return result;
}


void	*write_func(void *p)
{
	QUEUE_T *p_queue = (QUEUE_T*)p;
	int		size = 0 ;
	BUFSZ	*ptr ;
#if 0
	u_char	*buffer ;

	buffer = calloc(WRITE_SIZE, sizeof(char));
	if(buffer == NULL){
		return NULL ;
	}
#endif

	while(1){
		ptr = dequeue(p_queue);
		if(ptr == NULL){
			close(wfd);
			break ;
		}
#if 0
		if((size + ptr->size) < WRITE_SIZE){
			memcpy((buffer + size) , ptr->buffer, ptr->size);
			size += ptr->size ;
		}else{
			write(wfd, buffer, size);
			size = ptr->size ;
		}
#endif
		write(wfd, ptr->buffer, ptr->size);
		free(ptr);
		if((f_exit) && (!p_queue->no_empty)){
#if 0
			if(size){
				write(wfd, buffer, size);
			}
#endif
			close(wfd);
			break ;
		}
	}
	return NULL;
}

int main(int argc, char **argv)
{
	int		fd ;
	int		rc ;
	int		lp ;
	int		channel ;
	int		recsec ;
	time_t	start_time ;
	time_t	cur_time ;
	FREQUENCY	freq;
	ISDB_T_FREQ_CONV_TABLE	*ptr ;
	pthread_t dequeue_threads;
	QUEUE_T *p_queue = create_queue(MAX_QUEUE);
	BUFSZ	*bufptr ;

	if(argc < 4){
		printf("Usage %s: channel recsec destfile\n", argv[0]);
		printf("channel =\n");
		printf("151ch:BS朝日\n");
		printf("161ch:BS-i\n");
		printf("171ch:BSジャパン\n");
		printf("211ch:BS11デジタル\n");
		printf("222ch:TwellV\n");
		printf("141ch:BS日テレ\n");
		printf("181ch:BSフジ\n");
		printf("101ch:NHK衛星第1放送(BS1)\n");
		printf("102ch:NHK衛星第2放送(BS2)\n");
		printf("103ch:NHKハイビジョン(BShi)\n");
		return 1;
	}
	ptr = searchrecoff(argv[1]);
	if(ptr == NULL){
		printf("Channel Select Error(%s)\n", argv[1]);
		return 1 ;
	}

	freq.frequencyno = ptr->set_freq ;
	freq.slot = ptr->add_freq ;

	if(ptr->type == CHTYPE_SATELLITE){
		for(lp = 0 ; lp < 2 ; lp++){
			fd = open(bsdev[lp], O_RDONLY);
			if(fd >= 0){
				break ;
			}
		}
		if(fd < 0){
			printf("Device Open Error\n");
			return 1;
		}
	}else{
		for(lp = 0 ; lp < 2 ; lp++){
			fd = open(isdb_t_dev[lp], O_RDONLY);
			if(fd >= 0){
				break ;
			}
		}
		if(fd < 0){
			printf("Device Open Error\n");
			return 1;
		}
	}
	recsec = atoi(argv[2]);

	wfd = open64(argv[3], (O_RDWR | O_CREAT | O_TRUNC), 0666);
	if(wfd < 0){
		printf("Output File Open Error(%s)\n", argv[3]);
		return 0;
	}

	if(ioctl(fd, SET_CHANNEL, &freq) < 0){
		printf("Tuner Select Error\n");
		return 0 ;
	}
	pthread_create(&dequeue_threads, NULL, write_func, p_queue);
	if(ioctl(fd, START_REC, 0) < 0){
		printf("Tuner Start Error\n");
		return 0 ;
	}

	time(&start_time);
	while(1){
		time(&cur_time);
		bufptr = calloc(1, sizeof(BUFSZ));
		bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE);
		if(bufptr->size <= 0){
			if((cur_time - start_time) >= recsec){
				f_exit = TRUE ;
				enqueue(p_queue, NULL);
				break ;
			}else{
				continue ;
			}
		}
		enqueue(p_queue, bufptr);

		if((cur_time - start_time) >= recsec){
			ioctl(fd, STOP_REC, 0);
			//なくなるまでデータを読み出す
			while(1){
				bufptr = calloc(1, sizeof(BUFSZ));
				bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE);
				if(bufptr->size <= 0){
					f_exit = TRUE ;
					enqueue(p_queue, NULL);
					break ;
				}
				enqueue(p_queue, bufptr);
			}
			break ;
		}
	}
	close(fd);
	pthread_join(dequeue_threads, NULL);
	destroy_queue(p_queue);
	return 0 ;
}