view src/tssplitter_lite.h @ 146:066f33b2213a

EXPERIMENTAL: Select a particular program from multi-channel.
author Naoya OYAMA <naoya.oyama@gmail.com>
date Tue, 21 Aug 2012 04:21:11 +0900
parents bf96eac4dbb1
children 7d8a5bb874ad
line wrap: on
line source

/* -*- tab-width: 4; indent-tabs-mode: t -*- */
/* vim: set ts=4 sts=4 sw=4 noexpandtab number : */
/* tssplitter_lite.h  -- split TS stream program's header.

   Copyright 2009 querulous
   Copyright 2010-2012 Naoya OYAMA <naoya.oyama@gmail.com>

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
#ifndef _TS_SPLITTER_LITE_H_
#define _TS_SPLITTER_LITE_H_

#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <unistd.h>
#include <limits.h>

#define LENGTH_PACKET		(188)
#define MAX_PID				(8192)
#define MAX_SERVICES		(50)
#define LENGTH_CRC_DATA		(176)
#define false				(0)
#define true				(1)

#define TSS_SUCCESS			(0)
#define TSS_ERROR			(-1)
#define TSS_NULL			(-2)
#define LENGTH_PAT_HEADER	(12)
#define C_CHAR_COMMA		','
#define C_CHAR_DOT			'.'
#define LENGTH_TS_HEADER (4)
#define LENGTH_PES_HEADER (9)
#define LENGTH_PTS (5)

/* 改訂版デジタル放送教科書(上) P101 表1 ARIBでのPSI/SIの種類より参照 */
#define PAT					(0x0000)
//#define PMT						 /* PATによる間接指定 */
#define CAT					(0x0001)
#define NIT					(0x0010)
#define SDT					(0x0011)
#define BAT					(0x0011)
#define EIT					(0x0012) /* 0x0026, 0x0027 */
#define RST					(0x0013)
#define TDT					(0x0014) /* 地デジでは使用されない */
#define TOT					(0x0014)
#define LIT					(0x0020) /* またはPMTによる間接指定 */
#define	ERT					(0x0021) /* またはPMTによる間接指定 */
//#define ITT						 /* PMTによる間接指定 */
#define PCAT				(0x0022)
#define BIT					(0x0024)
#define NBIT				(0x0025)
//#define ECM						 /* PMTによる間接指定 */
//#define EMM						 /* CATによる間接指定 */
#define LDT					(0x0025)
#define DCT					(0x0017)
//#define DTL						 /* DCTによる間接指定 */
#define DIT					(0x001e)
#define SIT					(0x001f)
#define SDTT				(0x0023)
#define CDT					(0x0029)
//#define DSM-CC_Section			 /* PMTによる間接指定 */

/* セクションヘッダ長 */
/* TS パケットに各セクションを設置する際、該当TSパケットの残サイズが
 * いくつ以上あれば書き込めるかの判定に使用する。
 * デコードにはあまり重要では無いかも
 */
#define SECTION_LENGTH_PAT	(8)
#define SECTION_LENGTH_PMT	(8)
#define SECTION_LENGTH_CAT	(8)
#define SECTION_LENGTH_NIT	(8)
#define SECTION_LENGTH_BIT	(8)
#define SECTION_LENGTH_SDT	(11)
#define SECTION_LENGTH_EIT	(14) /* H-EIT, M-EIT, L-EIT を示す */
#define SECTION_LENGTH_SDTT	(15)
#define SECTION_LENGTH_CDT	(13)
#define SECTION_LENGTH_TOT	(10)

enum {
	PTS_FLAG = 0x80,
	DTS_FLAG = 0x40,
	ESCR_FLAG = 0x20,
	ES_RATE_FLAG = 0x10,
	DSM_TRICK_MODE_FLAG = 0x08,
	COPY_INFO_FLAG = 0x04,
	CRC_FLAG = 0x02,
	EXTENSION_FLAG = 0x01
};

enum {
	PES_PRIVATE_DATA_FLAG = 0x80,
	PACK_HEADER_FIELD_FLAG = 0x40,
	PROGRAM_PACKET_SEQUENCE_COUNTER = 0x20,
	PSTD_BUFFER_FLAG = 0x10,
	PES_EXTENSION_FLAG2 = 0x01
};

/*
 * PCRからSTCを生成する処理方式
 * 1. PCRを二つ取得するまでループ(1.から4.までは初期処理で実施すること)
 * 2. ループ開始時刻(PCR)と、ループ抜けた時刻(PCR)の差分を取る
 * 3. ループ開始〜終了の間に処理したパケット数を数える
 * 4. (2.のPCRの進んだ時間/3.のパケット数) の計算によって、1パケットによって進むPCRを想定する
 * 5. TS受信時に、1つのパケットを処理する度に4.の想定する経過時刻をPCRに足し込んでSTCとする
 * 6. PCRを新規に取得したら、STCを補正(そのまま代入)する
 */
#define MAX_VIDEO (16)
#define MAX_AUDIO (32)
typedef struct _program_t
{
	int64_t stc;
	int64_t cue;		/* 録画開始時刻 */
	int pmt_packet_id;	/* 該当Program(Service ID)に対応するPMT */
	int pmt_version;	/* 該当Program(Service ID)に対応するPMTのVersion */
	int pcr_packet_id;	/* 該当Program(Service ID)のPCRを保持するPID */
	int64_t pcr1;	/* PCR1 */
	int64_t pcr2;	/* PCR2 */
	int pcr_packet_nb;	/* 直前のPCRを受信したときのパケット数 */
	int packet_nb;	/* 直前のProgramの処理を実施したときのパケット数 */
	int64_t pcr_incr;	/* 該当Program(Service ID)に於いて、1つのTSパケットを処理した時に経過する(と想定する時間) */
	int video_start;		/* VODEO0を蓄積開始している? */
	int64_t video_pts;		/* 最後に処理したVODEO0のESのPTS */
	int video_nb;			/* PMT に存在するビデオストリームの数 */
	int audio_nb;			/* PMT に存在する音声ストリームの数 */
	int video[MAX_VIDEO];	/* PS出力する場合に使うかも */
	int audio[MAX_AUDIO];	/* PS出力する場合に使うかも */
} program_t;
/*
 * program_t をサービスID分準備して、使用するイメージでいたけど、
 * サービスIDの最大値は0xFFFFであるので、静的に確保すると stack が簡単に溢るので、
 * 実行時に malloc とするかなぁ
 * 本当は必要なだけallocするのが好ましいのだけど…
 */

typedef struct _splitpesbuf_t
{
	program_t *Program;
	int64_t pts;
	int64_t dts;
    int size;
    u_char buffer[3*1024*1024];
} splitpesbuf_t;

typedef struct _splitesbuf_t
{
	program_t *Program;
	int64_t pts;
	int64_t dts;
	int started; /* 該当ESが蓄積開始しているか */
	int random_access_indicator; /* TS の random_access_indicator */
	int fd; /* 該当ESのfd */
    int size;
    u_char buffer[3*1024*1024];
} splitesbuf_t;

/* PCR 共有用構造体 */
typedef struct _pcr_t
{
	int pid;
	int sid_nb; /* PCRを参照しているServiceID(ProgramID)の数 */
	int sid[MAX_SERVICES];
} pcr_t;


/**
 * splitter構造体
 */
typedef struct splitter {
	char *filename; /* ファイル名を上位からもらってくるためのポインタ */
	char *arg_cue; /* 引数で取得してきた録画開始時刻(HHMISS) */
	int esout; /* ES出力する? */
	unsigned char	pids[MAX_PID];
	unsigned char	pmt_pids[MAX_PID];
	uint8_t			cat_pids[MAX_PID];
	uint8_t			pcr_pids[MAX_PID]; /* PCRは複数ServiceID(ProgramID)で共有される */
	pcr_t			pcr[MAX_SERVICES];
	int				pcr_nb;
	unsigned char*	pat;
	char**			sid_list;
	unsigned char	pat_count;
	int pmt_retain;
	int pmt_counter;
	int avail_pmts[MAX_SERVICES];
	int num_pmts;
	splitpesbuf_t *pesbuf[MAX_PID];
	splitesbuf_t *esbuf[MAX_PID];
	program_t *program;
	int pid_sid_table[MAX_PID]; /* pid to sid の変換を行うためのテーブル */
	time_t time_cue;
	time_t time_tot;
	int tot_packet_nb; /* TOT受信時のパケット受信数 */
} splitter;

/* b25 decoder would hoard up large chank */
typedef struct _splitbuf_t
{
    int size;
    int buffer_length;
    u_char *buffer;
} splitbuf_t;

splitter* split_startup(char *sid, char *filename, char *cue_time);
int split_select(splitter *sp, ARIB_STD_B25_BUFFER *sbuf);
void split_shutdown(splitter *sp);
int split_ts(splitter *splitter, ARIB_STD_B25_BUFFER *sbuf, splitbuf_t *dbuf);

#endif