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

📄 aviobuf.c

📁 ts流的解复用
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -