📄 transport_stream.c
字号:
/******************************************************************
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 + -