view recpt1/recpt1.c @ 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
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"

#include "recpt1.h"
#include "decoder.h"

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


// 周波数テーブル変換
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;
}

/* this function will be a writing thread */
void *
write_func(void *p)
{
  QUEUE_T *p_queue = (QUEUE_T*)p;
  BUFSZ	*ptr ;
  ARIB_STD_B25_BUFFER sbuf, dbuf;

  while(1){
    ptr = dequeue(p_queue);
    /* no entry in the queue */
    if(ptr == NULL){
      close(wfd);
      break ;
    }

    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		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 ;
  }

  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]);

  /* 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);

  /* 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((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); /* close tuner */

  /* wait reading thread */
  pthread_join(dequeue_threads, NULL);
  destroy_queue(p_queue);

  /* release decoder */
  b25_shutdown(dec);

  return 0 ;
}