view recpt1/recpt1.c @ 3:6801fe7e04ff

updated to ariv25v023
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Tue, 17 Feb 2009 01:40:56 +0900
parents 8ac7c59fefc9
children 43d177fa65c9
line wrap: on
line source

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

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

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

/* globals */
int	wfd;		/* for output file */
int	f_exit = FALSE ;

typedef struct thread_data {
  QUEUE_T *queue;
  decoder *decoder;
} thread_data;

// 周波数テーブル変換
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 data. this function will block if queue is full. */
void
enqueue(QUEUE_T *p_queue, BUFSZ *data)
{
  pthread_mutex_lock(&p_queue->mutex);
  /* entered critical section */

  /* wait until queue is not full */
  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++;

  /* leaving critical section */
  pthread_mutex_unlock(&p_queue->mutex);
  pthread_cond_signal(&p_queue->cond_empty);
}

/* dequeue data. this function will block if queue is empty. */
BUFSZ *
dequeue(QUEUE_T *p_queue)
{
  BUFSZ	*buffer;

  pthread_mutex_lock(&p_queue->mutex);
  /* entered the critical section*/

  /* wait until queue is filled */
  while (!p_queue->no_empty) {
    pthread_cond_wait(&p_queue->cond_empty, &p_queue->mutex);
  }

  /* take buffer address */
  buffer = p_queue->buffer[p_queue->out];

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

  /* update flags */
  p_queue->no_full++;
  p_queue->no_empty--;

  /* leaving the critical section */
  pthread_mutex_unlock(&p_queue->mutex);
  pthread_cond_signal(&p_queue->cond_full);

  return buffer;
}

/* this function will be a writing thread */
void *
write_func(void *p)
{
  thread_data *data = (thread_data *)p;
  QUEUE_T *p_queue = data->queue;
  decoder *dec = data->decoder;
  BUFSZ	*buf ;
  ARIB_STD_B25_BUFFER sbuf, dbuf;

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

    sbuf.data = buf->buffer;
    sbuf.size = buf->size;

    /* write data to output file*/
    b25_decode(dec, &sbuf, &dbuf);
    write(wfd, dbuf.data, dbuf.size);
    free(buf);

    /* 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 ;
  decoder *dec;
  thread_data tdata;

  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 = open(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 */
  tdata.queue = p_queue;
  tdata.decoder = dec;
  pthread_create(&dequeue_threads, NULL, write_func, &tdata);

  /* start recording*/
  if(ioctl(fd, START_REC, 0) < 0) {
    printf("Tuner Start Error\n");
    return 0 ;
  }

  time(&start_time);

  /* read from tuner */
  while(1) {
    time(&cur_time);
    bufptr = malloc(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);

    /* stop recording */
    if((cur_time - start_time) >= recsec) {
      ioctl(fd, STOP_REC, 0);
      /* read remaining data */
      while(1) {
	bufptr = malloc(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 tuner */
  close(fd);

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

  /* release decoder */
  b25_shutdown(dec);

  return 0 ;
}