changeset 2:8ac7c59fefc9

added b25 decode functionality
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 16 Feb 2009 21:40:16 +0900
parents 29f3b2bbbd67
children 6801fe7e04ff
files recpt1/Makefile recpt1/decoder.c recpt1/decoder.h recpt1/recpt1.c recpt1/recpt1.h
diffstat 5 files changed, 324 insertions(+), 232 deletions(-) [+]
line wrap: on
line diff
--- a/recpt1/Makefile	Mon Feb 16 15:55:46 2009 +0900
+++ b/recpt1/Makefile	Mon Feb 16 21:40:16 2009 +0900
@@ -18,7 +18,7 @@
 CFLAGS =	-O2 -g -Wall -pthread -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 $(B25) -I../driver
 LDFLAGS  = 
 
-OBJS   = recpt1.o $(B25_OBJS_EXT)
+OBJS   = recpt1.o $(B25_OBJS_EXT) decoder.o
 LIBS   = -lpthread 
 TARGET = $(DIST)/recpt1
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/recpt1/decoder.c	Mon Feb 16 21:40:16 2009 +0900
@@ -0,0 +1,56 @@
+#include <stdlib.h>
+
+#include "decoder.h"
+
+decoder *
+b25_startup(void)
+{
+  decoder *dec = calloc(1, sizeof(decoder));
+  int code;
+
+  dec->b25 = create_arib_std_b25();
+  dec->b25->set_multi2_round(dec->b25, 4); //xxx round should be configurable
+  dec->b25->set_strip(dec->b25, 0); //ditto
+  dec->b25->set_emm_proc(dec->b25, 0); //ditto
+  dec->bcas = create_b_cas_card();
+  code = dec->bcas->init(dec->bcas);
+  code = dec->b25->set_b_cas_card(dec->b25, dec->bcas);
+
+  return dec;
+}
+
+int
+b25_shutdown(decoder *dec)
+{
+  dec->b25->release(dec->b25);
+  dec->bcas->release(dec->bcas);
+  free(dec);
+
+  return 0;
+}
+
+int
+b25_decode(decoder *dec, ARIB_STD_B25_BUFFER *sbuf, ARIB_STD_B25_BUFFER *dbuf)
+{
+  int code;
+
+  code = dec->b25->put(dec->b25, sbuf);
+  if(code < 0)
+    return code;
+
+  code = dec->b25->get(dec->b25, dbuf);
+  return code;
+}
+
+int
+b25_finish(decoder *dec, ARIB_STD_B25_BUFFER *sbuf, ARIB_STD_B25_BUFFER *dbuf)
+{
+  int code;
+
+  code = dec->b25->flush(dec->b25);
+  if(code < 0)
+    return code;
+
+  code = dec->b25->get(dec->b25, dbuf);
+  return code;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/recpt1/decoder.h	Mon Feb 16 21:40:16 2009 +0900
@@ -0,0 +1,23 @@
+#ifndef _DECODER_H_
+#define _DECODER_H_
+
+#include "../arib25v021/arib25/src/arib_std_b25.h"
+#include "../arib25v021/arib25/src/b_cas_card.h"
+
+typedef struct decoder
+{
+  ARIB_STD_B25 *b25;
+  B_CAS_CARD *bcas;
+} decoder;
+
+/* prototypes */
+decoder *b25_startup(void);
+int b25_shutdown(decoder *dec);
+int b25_decode(decoder *dec,
+	       ARIB_STD_B25_BUFFER *sbuf,
+	       ARIB_STD_B25_BUFFER *dbuf);
+int b25_finish(decoder *dec,
+	       ARIB_STD_B25_BUFFER *sbuf,
+	       ARIB_STD_B25_BUFFER *dbuf);
+
+#endif
--- a/recpt1/recpt1.c	Mon Feb 16 15:55:46 2009 +0900
+++ b/recpt1/recpt1.c	Mon Feb 16 21:40:16 2009 +0900
@@ -11,271 +11,287 @@
 #include	<sys/ioctl.h>
 #include	"pt1_ioctl.h"
 
-#include	"recpt1.h"
+#include "recpt1.h"
+#include "decoder.h"
+
+/* globals */
+int	wfd;		// ファイル書き込み用
+int	f_exit = FALSE ;
+decoder *dec;
 
 
 // 周波数テーブル変換
-ISDB_T_FREQ_CONV_TABLE	*searchrecoff(char *channel)
+ISDB_T_FREQ_CONV_TABLE *
+searchrecoff(char *channel)
 {
-	int		lp ;
+  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 ;
+  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 *
+create_queue(size_t size)
 {
-	QUEUE_T*	p_queue;
-	int		memsize = sizeof(QUEUE_T) + (size * sizeof(BUFSZ));
+  QUEUE_T*	p_queue;
+  int		memsize = sizeof(QUEUE_T) + (size * sizeof(BUFSZ));
 
-	p_queue = (QUEUE_T*)calloc(memsize, sizeof(char));
+  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);
-	}
+  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;
+  return p_queue;
 }
 
-void	destroy_queue(QUEUE_T *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);
-	}
+  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)
+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");
-	}
+  pthread_mutex_lock(&p_queue->mutex);
+  // -- ここから、クリティカルセクション --
 
-	p_queue->buffer[p_queue->in] = data;
+  // 満タンじゃなくなるまで待つ
+  while(!p_queue->no_full) {
+    pthread_cond_wait(&p_queue->cond_full, &p_queue->mutex);
+    printf("Full\n");
+  }
 
-	p_queue->in++;
-	p_queue->in %= p_queue->size;
+  p_queue->buffer[p_queue->in] = data;
 
-	p_queue->no_full--;
-	p_queue->no_empty++;
+  p_queue->in++;
+  p_queue->in %= p_queue->size;
 
-	pthread_mutex_unlock(&p_queue->mutex);
-	pthread_cond_signal(&p_queue->cond_empty);
+  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)
+BUFSZ *
+dequeue(QUEUE_T *p_queue)
 {
-	void	*result;
+  void	*result;
 
-	pthread_mutex_lock(&p_queue->mutex);
-	// -- ここから、クリティカルセクション --
+  pthread_mutex_lock(&p_queue->mutex);
+  // -- ここから、クリティカルセクション --
 
-	// 空っぽじゃなくなるまで待つ
-	while (!p_queue->no_empty) {
-		pthread_cond_wait(&p_queue->cond_empty, &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];
+  // データを取り出す
+  result = p_queue->buffer[p_queue->out];
 
-	// 次にデータを取り出す場所をインクリメント
-	p_queue->out++;
-	p_queue->out %= p_queue->size;
+  // 次にデータを取り出す場所をインクリメント
+  p_queue->out++;
+  p_queue->out %= p_queue->size;
 
-	// フラグの更新
-	p_queue->no_full++;
-	p_queue->no_empty--;
+  // フラグの更新
+  p_queue->no_full++;
+  p_queue->no_empty--;
 
-	// -- ここまで、クリティカルセクション --
-	pthread_mutex_unlock(&p_queue->mutex);
-	pthread_cond_signal(&p_queue->cond_full);
+  // -- ここまで、クリティカルセクション --
+  pthread_mutex_unlock(&p_queue->mutex);
+  pthread_cond_signal(&p_queue->cond_full);
 
-	return result;
+  return result;
 }
 
-
-void	*write_func(void *p)
+/* this function will be a writing thread */
+void *
+write_func(void *p)
 {
-	QUEUE_T *p_queue = (QUEUE_T*)p;
-	int		size = 0 ;
-	BUFSZ	*ptr ;
-#if 0
-	u_char	*buffer ;
+  QUEUE_T *p_queue = (QUEUE_T*)p;
+  BUFSZ	*ptr ;
+  ARIB_STD_B25_BUFFER sbuf, dbuf;
 
-	buffer = calloc(WRITE_SIZE, sizeof(char));
-	if(buffer == NULL){
-		return NULL ;
-	}
-#endif
+  while(1){
+    ptr = dequeue(p_queue);
+    /* no entry in the queue */
+    if(ptr == NULL){
+      close(wfd);
+      break ;
+    }
 
-	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;
+    sbuf.data = ptr->buffer;
+    sbuf.size = ptr->size;
+
+    /* write data to output file*/
+    b25_decode(dec, &sbuf, &dbuf);
+    write(wfd, dbuf.data, dbuf.size);
+    free(ptr);
+
+    /* normal exit */
+    if((f_exit) && (!p_queue->no_empty)){
+      b25_finish(dec, &sbuf, &dbuf);
+      write(wfd, dbuf.data, dbuf.size);
+      close(wfd);
+      break ;
+    }
+  }
+
+  return NULL;
 }
 
-int main(int argc, char **argv)
+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 ;
+  int		fd ;
+  int		lp ;
+  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 ;
-	}
+  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 ;
 
-	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]);
 
-	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]);
+  /* initialize decoder */
+  dec = b25_startup();
+
+  /* open output file */
+  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 ;
+  }
+
+  /* make reading thread */
+  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);
 
-	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;
-	}
+  /* read-write loop */
+  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(ioctl(fd, SET_CHANNEL, &freq) < 0){
-		printf("Tuner Select Error\n");
-		return 0 ;
+    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 ;
 	}
-	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);
+	enqueue(p_queue, bufptr);
+      }
+      break ;
+    }
+  }
+  close(fd); /* close tuner */
 
-		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 ;
+  /* wait reading thread */
+  pthread_join(dequeue_threads, NULL);
+  destroy_queue(p_queue);
+
+  /* release decoder */
+  b25_shutdown(dec);
+
+  return 0 ;
 }
--- a/recpt1/recpt1.h	Mon Feb 16 15:55:46 2009 +0900
+++ b/recpt1/recpt1.h	Mon Feb 16 21:40:16 2009 +0900
@@ -10,12 +10,12 @@
 	"/dev/pt1video3"
 };
 
-#define		CHTYPE_SATELLITE		0		// 衛星デジタル放送
-#define		CHTYPE_GROUND			1		// 地上デジタル放送
-#define		MAX_QUEUE				8192
+#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		WRITE_SIZE	(1024 * 1024 * 2)
 #define		TRUE	1
 #define		FALSE	0
 
@@ -25,20 +25,17 @@
 }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];			// バッファポインタ
+  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 ;					// チャンネルタイプ