⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transport_stream.c

📁 由bmp生成mpeg2 的I_frame 数据
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************
                       Transport Stream module
 ******************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include "pes.h"
#include "001.h"
#include "registry.h"

#include "multi_file.h"

#define TRANSPORT_STREAM_C
#include "transport_stream.h"

typedef struct {

	MULTI_FILE     *mf;
	char           *path;

	unsigned char  *buffer;
	unsigned char  *current;
	int             buffer_size;
	int             buffer_max;
	
	int             pid;

	int             unit_size;
	int             offset;
	
	__int64         file_length;
	
	PES_STREAM_TYPE type;

	unsigned char  *data;
	unsigned int    data_rest;
	__int64         pos;

	unsigned char   *data_buffer;
} TRANSPORT_STREAM;

typedef struct {
	int sync;
	int transport_error_indicator;
	int payload_unit_start_indicator;
	int transport_priority;
	int pid;
	int transport_scrambling_control;
	int adaptation_field_control;
	int continuity_counter;
} TS_HEADER;

int ts_open(const char *filename, int stream_type);
int ts_close(int in);
int ts_read(int in, void *data, unsigned int count);
__int64 ts_seek(int in, __int64 offset, int origin);
__int64 ts_tell(int in);

static int check_transport_stream(TRANSPORT_STREAM *ts);
static int reserve_buffer(TRANSPORT_STREAM *ts);
static void count_file_size(TRANSPORT_STREAM *ts);
static int fill_buffer(TRANSPORT_STREAM *ts);
static unsigned char *read_unit(TRANSPORT_STREAM *ts);
static void go_next_unit(TRANSPORT_STREAM *ts);
static void go_prev_unit(TRANSPORT_STREAM *ts);
static __int64 ts_seek_raw(TRANSPORT_STREAM *ts, __int64 offset, int origin);
static __int64 ts_tell_raw(TRANSPORT_STREAM *ts);
static int select_stream(TRANSPORT_STREAM *ts);
static void extract_ts_header(unsigned char *buffer, TS_HEADER *header);
static int read_pes_packet(TRANSPORT_STREAM *ts, PES_PACKET *out);
static void reserve_data_buffer(TRANSPORT_STREAM *ts, int size);
static void extract_program_association_table(unsigned char *buffer, unsigned char *pid_type);
static int extract_program_map_table(unsigned char *buffer, unsigned char *pid_type, int type);

int ts_open(const char *filename, int stream_type)
{
	int n;
	TRANSPORT_STREAM *ts;

	ts = (TRANSPORT_STREAM *)calloc(1, sizeof(TRANSPORT_STREAM));
	if(ts == NULL){
		return -1;
	}

	n = strlen(filename)+1;
	ts->path = (char *)malloc(n);
	if(ts->path == NULL){
		free(ts);
		return -1;
	}
	memcpy(ts->path, filename, n);

	ts->mf = open_multi_file(filename);
	if(ts->mf == NULL){
		free(ts->path);
		free(ts);
		return -1;
	}
	
	if(!check_transport_stream(ts)){
		ts->mf->close(ts->mf);
		free(ts->path);
		free(ts);
		return -1;
	}

	if(!reserve_buffer(ts)){
		ts->mf->close(ts->mf);
		free(ts->path);
		free(ts);
		return -1;
	}

	count_file_size(ts);

	fill_buffer(ts);

	ts->type.type = stream_type;
	if(!select_stream(ts)){ /* failed to find stream */
		ts_close((int)ts);
		return -1;
	}
	ts_seek((int)ts, 0, SEEK_SET);

	return (int)ts;
}

int ts_close(int in)
{
	TRANSPORT_STREAM *ts;

	ts = (TRANSPORT_STREAM *)in;

	if(in == -1){
		return 0;
	}
	
	if(ts == NULL){
		return 0;
	}

	if(ts->path){
		free(ts->path);
		ts->path = NULL;
	}

	if(ts->buffer){
		free(ts->buffer);
		ts->buffer = NULL;
	}

	if(ts->data_buffer){
		free(ts->data_buffer);
		ts->data_buffer = NULL;
	}

	if(ts->mf){
		ts->mf->close(ts->mf);
		ts->mf = NULL;
	}
	
	free(ts);

	return 1;
}

int ts_read(int in, void *data, unsigned int count)
{
	int r;
	
	TRANSPORT_STREAM *ts;
	PES_PACKET packet;
	PES_STREAM_TYPE type;

	init_pes_packet(&packet);
	ts = (TRANSPORT_STREAM *)in;

	if(ts->data_rest){
		if(ts->data_rest <= count){
			memcpy(data, ts->data, ts->data_rest);
			r = ts->data_rest;
			ts->data = ts->data_buffer + ts->data_rest;
			ts->data_rest = 0;
			
			release_pes_packet(&packet);
			return r;
		}else{
			memcpy(data, ts->data, count);
			ts->data_rest -= count;
			ts->data += count;
			
			release_pes_packet(&packet);
			return count;
		}
	}

	r = 0;
	while(read_pes_packet(ts, &packet)){
		if(extract_pes_stream_type(&packet, &type)){
			if( (type.type == ts->type.type) && (type.id == ts->type.id) ){
				reserve_data_buffer(ts, get_pes_packet_data_length(&packet));
				extract_pes_packet_data(&packet, ts->data_buffer, &(ts->data_rest));
				if(ts->data_rest <= count){
					memcpy(data, ts->data_buffer, ts->data_rest);
					r = ts->data_rest;
					ts->data = ts->data_buffer + ts->data_rest;
					ts->data_rest = 0;
					
					release_pes_packet(&packet);
					return r;
				}else{
					memcpy(data, ts->data_buffer, count);
					ts->data_rest -= count;
					ts->data = ts->data_buffer + count;
					
					release_pes_packet(&packet);
					return count;
				}
			}
		}
	}

	release_pes_packet(&packet);
	return r;
}

__int64 ts_seek(int in, __int64 offset, int origin)
{
	__int64           n;
	int               start_indicator;
	unsigned char    *p;
	TRANSPORT_STREAM *ts;
	TS_HEADER         header;
	PES_PACKET        packet;
	PES_STREAM_TYPE   type;
	
	init_pes_packet(&packet);
	ts = (TRANSPORT_STREAM *)in;

	offset = ts_seek_raw(ts, offset, origin);
	n = offset % ts->unit_size;
	n = ts_seek_raw(ts, -n, SEEK_CUR);
	
	ts->pos = n;
	ts->data = ts->data_buffer;
	ts->data_rest = 0;
	
	start_indicator = 0;
	while( (p = read_unit(ts)) != NULL ){
		extract_ts_header(p, &header);
		if(ts->pid == header.pid){
			if(start_indicator){
				break;
			}
			if(header.payload_unit_start_indicator){
				start_indicator = 1;
			}
		}
		go_prev_unit(ts);
		if(ts_tell_raw(ts) == 0){
			break;
		}
	}

	start_indicator = 0;
	while( read_pes_packet(ts, &packet) ){
		if(extract_pes_stream_type(&packet, &type)){
			if( (type.type == ts->type.type) && (type.id == ts->type.id) ){
				n = offset - ts->pos;
				if(n < 0){
					n = 0;
				}
				reserve_data_buffer(ts, get_pes_packet_data_length(&packet));
				extract_pes_packet_data(&packet, ts->data_buffer, &(ts->data_rest));
				if(n < ts->data_rest){
					ts->data_rest -= (int)n;
					ts->data = ts->data_buffer + (int)n;
					break;
				}
			}
		}
	}
	
	release_pes_packet(&packet);
	return ts_tell(in);		
}

__int64 ts_tell(int in)
{
	__int64           r;
	TRANSPORT_STREAM *ts;

	ts = (TRANSPORT_STREAM *)in;

	r = ts->pos + (ts->data - ts->data_buffer);

	return r;
}

static int check_transport_stream(TRANSPORT_STREAM *ts)
{
	int i,n;
	unsigned char buffer[6144];

	ts->mf->seek(ts->mf, 0, SEEK_SET);
	n = ts->mf->read(ts->mf, buffer, sizeof(buffer));
	ts->mf->seek(ts->mf, 0, SEEK_SET);
	
	for(i=0;i<n;i+=188){
		if(buffer[i] != 0x47){
			break;
		}
	}

	if(i>=n){
		ts->unit_size = 188;
		ts->offset = 0;
		return 1;
	}

	for(i=0;i<n;i+=192){
		if(buffer[i+4] != 0x47){
			break;
		}
	}

	if(i>=n){
		ts->unit_size = 192;
		ts->offset = 4;
		return 1;
	}

	for(i=0;i<n;i+=204){
		if(buffer[i] != 0x47){
			break;
		}
	}
	
	if(i>=n){
		ts->unit_size = 204;
		ts->offset = 0;
		return 1;
	}

	return 0;
}

static int reserve_buffer(TRANSPORT_STREAM *ts)
{
	int gcd,lcm;
	int m,n;
	int min = 512*1024;

	m = ts->unit_size;
	n = 4096;

	while(m!=n){
		if(m>n){
			m = m-n;
		}else{
			n = n-m;
		}
	}

	gcd = m;
	lcm = 4096/gcd*ts->unit_size;
	ts->buffer_max = lcm;
	while(ts->buffer_max < min){
		ts->buffer_max += lcm;
	}

	ts->buffer = (unsigned char *)malloc(ts->buffer_max);
	if(ts->buffer == NULL){
		return 0;
	}

	return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -