📄 aviobuf.c
字号:
#include <stdio.h>
#include <stdlib.h>
#include "aviobuf.h"
#include "ringbuffer.h"
#include "avformat.h"
#include "avcodec.h"
#include "packet.h"
#include "dvbpsi.h"
#include "psi.h"
#include "pat.h"
#include "descriptor.h"
#include "tables/pmt.h"
#include "descriptors/dr.h"
#define RINGBUFFER_SIZE (1*1024)
#define MAX_RESYNC_SIZE 4096
#define TS_PACKET_SIZE 188
char *filename = "C:\\Documents and Settings\\Administrator\\桌面\\FFmpeg-full-SDK-3.2\\bin\\bbc.ts";
#define SYSTEM_CLOCK_DR 0x0B
#define MAX_BITRATE_DR 0x0E
#define STREAM_IDENTIFIER_DR 0x52
#define SUBTITLING_DR 0x59
FILE *fp=NULL;
FILE *wfp;
typedef struct
{
int program_id;
int pmt_pid;
dvbpsi_handle handle;
}PMT_ENTRY;
PMT_ENTRY pmt_array[100];
int pmt_count=0;
int scan_pat = 0;
void DumpPMT(void* p_zero, dvbpsi_pmt_t* p_pmt);
//从缓冲里读取指定字节,拷贝方式
int get_buffer(RingBuffer_s *s, unsigned char *buf, int size)
{
int len, size1;
int free;
size1 = size;
while (size > 0)
{
len = rb_avail(s);
if (len > size) len = size;
else
{
free = rb_free(s);
//读数据填充rb
if(rb_fill(s, fp, free) == 0) return 0;
//printf("fread %d ok\n", free);
continue;
}
//从rb里读数据
rb_read(s, buf, len);
buf += len;
size -= len;
}
return size1 - size;
}
static int mpegts_resync(RingBuffer_s *pb)
{
int i, len;
u8 c[1];
for(i = 0;i < MAX_RESYNC_SIZE; i++)
{
len = get_buffer(pb, c, 1);
if (len < 0)
return -1;
if (c[0] == 0x47) {
rb_backspace(pb, -1);
printf("offset = %d \n", i);
return 0;
}
}
/* no sync found */
return -1;
}
//从缓冲里读一个ts包
int read_packet(RingBuffer_s *pb, uint8_t *buf, int raw_packet_size)
{
int skip, len, size;
for(;;)
{
len = get_buffer(pb, buf, TS_PACKET_SIZE);
if (len != TS_PACKET_SIZE)
return -1;
/* check paquet sync byte */
if (buf[0] != 0x47)
{
/* find a new packet start */
rb_backspace(pb, -TS_PACKET_SIZE);
if (mpegts_resync(pb) < 0)
return -2;
else
continue;
} else {
//printf("sync...\n");
break;
}
}
return 0;
}
//初始化循环缓冲
void avio_init(RingBuffer_s *rb, int size)
{
u8 *buf;
buf = (u8*)malloc(size);
if(!buf) return ;
printf("ts buffer addr 0x%x\n", buf);
fp = fopen(filename, "rb");
if(!fp) return;
printf("open file ok..\n");
//填充缓冲
if(fread(buf, size, 1, fp))
{
rb_fill_init(rb, buf, size);
}
else
rb_init(rb, buf, size);
}
//#define PRINT fprintf(wfp,
static void hex_dump_internal(FILE *wfp, u8 *buf, int size)
{
int len, i, j, c;
for(i=0;i<size;i+=16) {
len = size - i;
if (len > 16)
len = 16;
fprintf(wfp, "%08x ", i);
for(j=0;j<16;j++) {
if (j < len)
fprintf(wfp, " %02x", buf[i+j]);
else
fprintf(wfp, " ");
}
fprintf(wfp, " ");
for(j=0;j<len;j++) {
c = buf[i+j];
if (c < ' ' || c > '~')
c = '.';
fprintf(wfp, "%c", c);
}
fprintf(wfp, "\n");
}
//#undef PRINT
}
#define PRINT printf
static void hex_dump(u8 *buf, int size)
{
int len, i, j, c;
for(i=0;i<size;i+=16) {
len = size - i;
if (len > 16)
len = 16;
PRINT("%08x ", i);
for(j=0;j<16;j++) {
if (j < len)
PRINT(" %02x", buf[i+j]);
else
PRINT(" ");
}
PRINT(" ");
for(j=0;j<len;j++) {
c = buf[i+j];
if (c < ' ' || c > '~')
c = '.';
PRINT("%c", c);
}
PRINT("\n");
}
}
/*****************************************************************************
* DumpPAT
*****************************************************************************/
void DumpPAT(void* p_zero, dvbpsi_pat_t* p_pat)
{
dvbpsi_pat_program_t* p_program = p_pat->p_first_program;
printf( "\n");
printf( "New PAT\n");
printf( " transport_stream_id : %d\n", p_pat->i_ts_id);
printf( " version_number : %d\n", p_pat->i_version);
printf( " | program_number @ [NIT|PMT]_PID\n");
while(p_program)
{
printf(" | %14d @ 0x%x (%d)\n",
p_program->i_number, p_program->i_pid, p_program->i_pid);
//注册一个pmt
pmt_array[pmt_count].program_id = p_program->i_number;
pmt_array[pmt_count].pmt_pid = p_program->i_pid;
pmt_array[pmt_count].handle = dvbpsi_AttachPMT(p_program->i_number, DumpPMT, NULL);
pmt_count++;
p_program = p_program->p_next;
}
printf( " active : %d\n", p_pat->b_current_next);
dvbpsi_DeletePAT(p_pat);
scan_pat = 1;
}
/*****************************************************************************
* GetTypeName
*****************************************************************************/
char* GetTypeName(uint8_t type)
{
switch (type)
{
case 0x00:
return "Reserved";
case 0x01:
return "ISO/IEC 11172 Video";
case 0x02:
return "ISO/IEC 13818-2 Video";
case 0x03:
return "ISO/IEC 11172 Audio";
case 0x04:
return "ISO/IEC 13818-3 Audio";
case 0x05:
return "ISO/IEC 13818-1 Private Section";
case 0x06:
return "ISO/IEC 13818-1 Private PES data packets";
case 0x07:
return "ISO/IEC 13522 MHEG";
case 0x08:
return "ISO/IEC 13818-1 Annex A DSM CC";
case 0x09:
return "H222.1";
case 0x0A:
return "ISO/IEC 13818-6 type A";
case 0x0B:
return "ISO/IEC 13818-6 type B";
case 0x0C:
return "ISO/IEC 13818-6 type C";
case 0x0D:
return "ISO/IEC 13818-6 type D";
case 0x0E:
return "ISO/IEC 13818-1 auxillary";
default:
if (type < 0x80)
return "ISO/IEC 13818-1 reserved";
else
return "User Private";
}
}
/*****************************************************************************
* DumpMaxBitrateDescriptor
*****************************************************************************/
void DumpMaxBitrateDescriptor(dvbpsi_max_bitrate_dr_t* bitrate_descriptor)
{
printf("Bitrate: %d\n", bitrate_descriptor->i_max_bitrate);
}
/*****************************************************************************
* DumpSystemClockDescriptor
*****************************************************************************/
void DumpSystemClockDescriptor(dvbpsi_system_clock_dr_t* p_clock_descriptor)
{
printf("External clock: %s, Accuracy: %E\n",
p_clock_descriptor->b_external_clock_ref ? "Yes" : "No",
p_clock_descriptor->i_clock_accuracy_integer *
pow(10.0, -(double)p_clock_descriptor->i_clock_accuracy_exponent));
}
/*****************************************************************************
* DumpStreamIdentifierDescriptor
*****************************************************************************/
void DumpStreamIdentifierDescriptor(dvbpsi_stream_identifier_dr_t* p_si_descriptor)
{
printf("Component tag: %d\n",
p_si_descriptor->i_component_tag);
}
/*****************************************************************************
* DumpSubtitleDescriptor
*****************************************************************************/
void DumpSubtitleDescriptor(dvbpsi_subtitling_dr_t* p_subtitle_descriptor)
{
int a;
printf("%d subtitles,\n", p_subtitle_descriptor->i_subtitles_number);
for (a = 0; a < p_subtitle_descriptor->i_subtitles_number; ++a)
{
printf(" | %d - lang: %c%c%c, type: %d, cpid: %d, apid: %d\n", a,
p_subtitle_descriptor->p_subtitle[a].i_iso6392_language_code[0],
p_subtitle_descriptor->p_subtitle[a].i_iso6392_language_code[1],
p_subtitle_descriptor->p_subtitle[a].i_iso6392_language_code[2],
p_subtitle_descriptor->p_subtitle[a].i_subtitling_type,
p_subtitle_descriptor->p_subtitle[a].i_composition_page_id,
p_subtitle_descriptor->p_subtitle[a].i_ancillary_page_id);
}
}
/*****************************************************************************
* DumpDescriptors
*****************************************************************************/
void DumpDescriptors(const char* str, dvbpsi_descriptor_t* p_descriptor)
{
int i;
while(p_descriptor)
{
printf("%s 0x%02x : ", str, p_descriptor->i_tag);
switch (p_descriptor->i_tag)
{
case SYSTEM_CLOCK_DR:
DumpSystemClockDescriptor(dvbpsi_DecodeSystemClockDr(p_descriptor));
break;
case MAX_BITRATE_DR:
DumpMaxBitrateDescriptor(dvbpsi_DecodeMaxBitrateDr(p_descriptor));
break;
case STREAM_IDENTIFIER_DR:
DumpStreamIdentifierDescriptor(dvbpsi_DecodeStreamIdentifierDr(p_descriptor));
break;
case SUBTITLING_DR:
DumpSubtitleDescriptor(dvbpsi_DecodeSubtitlingDr(p_descriptor));
break;
default:
printf("\"");
for(i = 0; i < p_descriptor->i_length; i++)
printf("%c", p_descriptor->p_data[i]);
printf("\"\n");
}
p_descriptor = p_descriptor->p_next;
}
};
/*****************************************************************************
* DumpPMT
*****************************************************************************/
void DumpPMT(void* p_zero, dvbpsi_pmt_t* p_pmt)
{
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es;
printf( "\n");
printf( "New active PMT\n");
printf( " program_number : %d\n",
p_pmt->i_program_number);
printf( " version_number : %d\n",
p_pmt->i_version);
printf( " PCR_PID : 0x%x (%d)\n",
p_pmt->i_pcr_pid, p_pmt->i_pcr_pid);
DumpDescriptors(" ]", p_pmt->p_first_descriptor);
printf( " | type @ elementary_PID\n");
while(p_es)
{
printf(" | 0x%02x (%s) @ 0x%x (%d)\n",
p_es->i_type, GetTypeName(p_es->i_type),
p_es->i_pid, p_es->i_pid);
DumpDescriptors(" | ]", p_es->p_first_descriptor);
p_es = p_es->p_next;
}
dvbpsi_DeletePMT(p_pmt);
}
//-------------------------------------------------------------------
enum MpegTSState {
MPEGTS_HEADER = 0,
MPEGTS_PESHEADER_FILL,
MPEGTS_PAYLOAD,
MPEGTS_SKIP,
};
/* enough for PES header + length */
#define PES_START_SIZE 9
#define MAX_PES_HEADER_SIZE (9 + 255)
#define AV_NOPTS_VALUE 0x8000000000000000
/* Start codes. */
#define SEQ_END_CODE 0x000001b7
#define SEQ_START_CODE 0x000001b3
#define GOP_START_CODE 0x000001b8
#define PICTURE_START_CODE 0x00000100
#define SLICE_MIN_START_CODE 0x00000101
#define SLICE_MAX_START_CODE 0x000001af
#define EXT_START_CODE 0x000001b5
#define USER_START_CODE 0x000001b2
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
struct unaligned_32 { uint32_t l; } ;
#define AV_RB32(a) (((const struct unaligned_32 *) (a))->l)
#define END_NOT_FOUND (-100)
struct PESContext {
int pid;
int stream_type;
// MpegTSContext *ts;
// AVFormatContext *stream;
// AVStream *st;
enum MpegTSState state;
/* used to get the format */
int data_index;
int total_size;
int pes_header_size;
int64_t pts, dts;
uint8_t header[MAX_PES_HEADER_SIZE];
};
static struct PESContext pes_data;
static struct PESContext *pes = &pes_data;
static int64_t get_pts(const uint8_t *p)
{
int64_t pts;
int val;
pts = (int64_t)((p[0] >> 1) & 0x07) << 30;
val = (p[1] << 8) | p[2];
pts |= (int64_t)(val >> 1) << 15;
val = (p[3] << 8) | p[4];
pts |= (int64_t)(val >> 1);
return pts;
}
const uint8_t *ff_find_start_code(const uint8_t * p, const uint8_t *end, uint32_t * state)
{
int i;
// assert(p<=end);
if(p>=end)
return end;
for(i=0; i<3; i++){
uint32_t tmp= *state << 8;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -