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

📄 mpegts.c

📁 arm平台下的H264编码和解码源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * MPEG2 transport stream (aka DVB) demux * Copyright (c) 2002-2003 Fabrice Bellard. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "avformat.h"#include "mpegts.h"//#define DEBUG_SI//#define DEBUG_SEEK/* 1.0 second at 24Mbit/s */#define MAX_SCAN_PACKETS 32000/* maximum size in which we look for synchronisation if   synchronisation is lost */#define MAX_RESYNC_SIZE 4096static int add_pes_stream(MpegTSContext *ts, int pid, int stream_type);enum MpegTSFilterType {    MPEGTS_PES,    MPEGTS_SECTION,};typedef void PESCallback(void *opaque, const uint8_t *buf, int len, int is_start);typedef struct MpegTSPESFilter {    PESCallback *pes_cb;    void *opaque;} MpegTSPESFilter;typedef void SectionCallback(void *opaque, const uint8_t *buf, int len);typedef void SetServiceCallback(void *opaque, int ret);typedef struct MpegTSSectionFilter {    int section_index;    int section_h_size;    uint8_t *section_buf;    int check_crc:1;    int end_of_section_reached:1;    SectionCallback *section_cb;    void *opaque;} MpegTSSectionFilter;typedef struct MpegTSFilter {    int pid;    int last_cc; /* last cc code (-1 if first packet) */    enum MpegTSFilterType type;    union {        MpegTSPESFilter pes_filter;        MpegTSSectionFilter section_filter;    } u;} MpegTSFilter;typedef struct MpegTSService {    int running:1;    int sid;    char *provider_name;    char *name;} MpegTSService;struct MpegTSContext {    /* user data */    AVFormatContext *stream;    int raw_packet_size; /* raw packet size, including FEC if present */    int auto_guess; /* if true, all pids are analized to find streams */    int set_service_ret;    int mpeg2ts_raw;  /* force raw MPEG2 transport stream output, if possible */    int mpeg2ts_compute_pcr; /* compute exact PCR for each transport stream packet */    /* used to estimate the exact PCR */    int64_t cur_pcr;    int pcr_incr;    int pcr_pid;        /* data needed to handle file based ts */    int stop_parse; /* stop parsing loop */    AVPacket *pkt; /* packet containing av data */    /******************************************/    /* private mpegts data */    /* scan context */    MpegTSFilter *sdt_filter;    int nb_services;    MpegTSService **services;        /* set service context (XXX: allocated it ?) */    SetServiceCallback *set_service_cb;    void *set_service_opaque;    MpegTSFilter *pat_filter;    MpegTSFilter *pmt_filter;    int req_sid;    MpegTSFilter *pids[NB_PID_MAX];};static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,                               const uint8_t *buf, int buf_size, int is_start){    MpegTSSectionFilter *tss = &tss1->u.section_filter;    int len;    unsigned int crc;        if (is_start) {        memcpy(tss->section_buf, buf, buf_size);        tss->section_index = buf_size;        tss->section_h_size = -1;        tss->end_of_section_reached = 0;    } else {        if (tss->end_of_section_reached)            return;        len = 4096 - tss->section_index;        if (buf_size < len)            len = buf_size;        memcpy(tss->section_buf + tss->section_index, buf, len);        tss->section_index += len;    }    /* compute section length if possible */    if (tss->section_h_size == -1 && tss->section_index >= 3) {        len = (((tss->section_buf[1] & 0xf) << 8) | tss->section_buf[2]) + 3;        if (len > 4096)            return;        tss->section_h_size = len;    }    if (tss->section_h_size != -1 && tss->section_index >= tss->section_h_size) {        if (tss->check_crc) {            crc = mpegts_crc32(tss->section_buf, tss->section_h_size);            if (crc != 0)                goto invalid_crc;        }        tss->section_cb(tss->opaque, tss->section_buf, tss->section_h_size);    invalid_crc:        tss->end_of_section_reached = 1;    }}MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int pid,                                          SectionCallback *section_cb, void *opaque,                                         int check_crc){    MpegTSFilter *filter;    MpegTSSectionFilter *sec;    #ifdef DEBUG_SI    printf("Filter: pid=0x%x\n", pid);#endif    if (pid >= NB_PID_MAX || ts->pids[pid])        return NULL;    filter = av_mallocz(sizeof(MpegTSFilter));    if (!filter)         return NULL;    ts->pids[pid] = filter;    filter->type = MPEGTS_SECTION;    filter->pid = pid;    filter->last_cc = -1;    sec = &filter->u.section_filter;    sec->section_cb = section_cb;    sec->opaque = opaque;    sec->section_buf = av_malloc(MAX_SECTION_SIZE);    sec->check_crc = check_crc;    if (!sec->section_buf) {        av_free(filter);        return NULL;    }    return filter;}MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid,                                      PESCallback *pes_cb,                                     void *opaque){    MpegTSFilter *filter;    MpegTSPESFilter *pes;    if (pid >= NB_PID_MAX || ts->pids[pid])        return NULL;    filter = av_mallocz(sizeof(MpegTSFilter));    if (!filter)         return NULL;    ts->pids[pid] = filter;    filter->type = MPEGTS_PES;    filter->pid = pid;    filter->last_cc = -1;    pes = &filter->u.pes_filter;    pes->pes_cb = pes_cb;    pes->opaque = opaque;    return filter;}void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter){    int pid;    pid = filter->pid;    if (filter->type == MPEGTS_SECTION)        av_freep(&filter->u.section_filter.section_buf);    else if (filter->type == MPEGTS_PES)        av_freep(&filter->u.pes_filter.opaque);    av_free(filter);    ts->pids[pid] = NULL;}static int analyze(const uint8_t *buf, int size, int packet_size, int *index){    int stat[packet_size];    int i;    int x=0;    int best_score=0;    memset(stat, 0, packet_size*sizeof(int));    for(x=i=0; i<size; i++){        if(buf[i] == 0x47){            stat[x]++;            if(stat[x] > best_score){                best_score= stat[x];                if(index) *index= x;            }        }        x++;        if(x == packet_size) x= 0;    }    return best_score;}/* autodetect fec presence. Must have at least 1024 bytes  */static int get_packet_size(const uint8_t *buf, int size){    int score, fec_score;    if (size < (TS_FEC_PACKET_SIZE * 5 + 1))        return -1;            score    = analyze(buf, size, TS_PACKET_SIZE, NULL);    fec_score= analyze(buf, size, TS_FEC_PACKET_SIZE, NULL);//    av_log(NULL, AV_LOG_DEBUG, "score: %d, fec_score: %d \n", score, fec_score);        if     (score > fec_score) return TS_PACKET_SIZE;    else if(score < fec_score) return TS_FEC_PACKET_SIZE;    else                       return -1;}typedef struct SectionHeader {    uint8_t tid;    uint16_t id;    uint8_t version;    uint8_t sec_num;    uint8_t last_sec_num;} SectionHeader;static inline int get8(const uint8_t **pp, const uint8_t *p_end){    const uint8_t *p;    int c;    p = *pp;    if (p >= p_end)        return -1;    c = *p++;    *pp = p;    return c;}static inline int get16(const uint8_t **pp, const uint8_t *p_end){    const uint8_t *p;    int c;    p = *pp;    if ((p + 1) >= p_end)        return -1;    c = (p[0] << 8) | p[1];    p += 2;    *pp = p;    return c;}/* read and allocate a DVB string preceeded by its length */static char *getstr8(const uint8_t **pp, const uint8_t *p_end){    int len;    const uint8_t *p;    char *str;    p = *pp;    len = get8(&p, p_end);    if (len < 0)        return NULL;    if ((p + len) > p_end)        return NULL;    str = av_malloc(len + 1);    if (!str)        return NULL;    memcpy(str, p, len);    str[len] = '\0';    p += len;    *pp = p;    return str;}static int parse_section_header(SectionHeader *h,                                 const uint8_t **pp, const uint8_t *p_end){    int val;    val = get8(pp, p_end);    if (val < 0)        return -1;    h->tid = val;    *pp += 2;    val = get16(pp, p_end);    if (val < 0)        return -1;    h->id = val;    val = get8(pp, p_end);    if (val < 0)        return -1;    h->version = (val >> 1) & 0x1f;    val = get8(pp, p_end);    if (val < 0)        return -1;    h->sec_num = val;    val = get8(pp, p_end);    if (val < 0)        return -1;    h->last_sec_num = val;    return 0;}static MpegTSService *new_service(MpegTSContext *ts, int sid,                                   char *provider_name, char *name){    MpegTSService *service;#ifdef DEBUG_SI    printf("new_service: sid=0x%04x provider='%s' name='%s'\n",            sid, provider_name, name);#endif    service = av_mallocz(sizeof(MpegTSService));    if (!service)        return NULL;    service->sid = sid;    service->provider_name = provider_name;    service->name = name;    dynarray_add(&ts->services, &ts->nb_services, service);    return service;}static void pmt_cb(void *opaque, const uint8_t *section, int section_len){    MpegTSContext *ts = opaque;    SectionHeader h1, *h = &h1;    const uint8_t *p, *p_end;    int program_info_length, pcr_pid, pid, stream_type, desc_length;    #ifdef DEBUG_SI    printf("PMT:\n");    av_hex_dump(stdout, (uint8_t *)section, section_len);#endif    p_end = section + section_len - 4;    p = section;    if (parse_section_header(h, &p, p_end) < 0)        return;#ifdef DEBUG_SI    printf("sid=0x%x sec_num=%d/%d\n", h->id, h->sec_num, h->last_sec_num);#endif    if (h->tid != PMT_TID || (ts->req_sid >= 0 && h->id != ts->req_sid) )        return;    pcr_pid = get16(&p, p_end) & 0x1fff;    if (pcr_pid < 0)        return;    ts->pcr_pid = pcr_pid;#ifdef DEBUG_SI    printf("pcr_pid=0x%x\n", pcr_pid);#endif    program_info_length = get16(&p, p_end) & 0xfff;    if (program_info_length < 0)        return;    p += program_info_length;    if (p >= p_end)        return;    for(;;) {        stream_type = get8(&p, p_end);        if (stream_type < 0)            break;        pid = get16(&p, p_end) & 0x1fff;        if (pid < 0)            break;        desc_length = get16(&p, p_end) & 0xfff;        if (desc_length < 0)            break;        p += desc_length;        if (p > p_end)            return;#ifdef DEBUG_SI        printf("stream_type=%d pid=0x%x\n", stream_type, pid);#endif        /* now create ffmpeg stream */        switch(stream_type) {        case STREAM_TYPE_AUDIO_MPEG1:        case STREAM_TYPE_AUDIO_MPEG2:        case STREAM_TYPE_VIDEO_MPEG1:        case STREAM_TYPE_VIDEO_MPEG2:        case STREAM_TYPE_VIDEO_MPEG4:        case STREAM_TYPE_VIDEO_H264:        case STREAM_TYPE_AUDIO_AAC:        case STREAM_TYPE_AUDIO_AC3:            add_pes_stream(ts, pid, stream_type);            break;        default:            /* we ignore the other streams */            break;        }    }    /* all parameters are there */    ts->set_service_cb(ts->set_service_opaque, 0);    mpegts_close_filter(ts, ts->pmt_filter);    ts->pmt_filter = NULL;}static void pat_cb(void *opaque, const uint8_t *section, int section_len){    MpegTSContext *ts = opaque;    SectionHeader h1, *h = &h1;    const uint8_t *p, *p_end;    int sid, pmt_pid;#ifdef DEBUG_SI    printf("PAT:\n");    av_hex_dump(stdout, (uint8_t *)section, section_len);#endif    p_end = section + section_len - 4;    p = section;    if (parse_section_header(h, &p, p_end) < 0)        return;    if (h->tid != PAT_TID)        return;    for(;;) {        sid = get16(&p, p_end);        if (sid < 0)            break;        pmt_pid = get16(&p, p_end) & 0x1fff;        if (pmt_pid < 0)            break;#ifdef DEBUG_SI        printf("sid=0x%x pid=0x%x\n", sid, pmt_pid);#endif        if (sid == 0x0000) {            /* NIT info */        } else {            if (ts->req_sid == sid) {                ts->pmt_filter = mpegts_open_section_filter(ts, pmt_pid,                                                             pmt_cb, ts, 1);                goto found;            }        }    }    /* not found */    ts->set_service_cb(ts->set_service_opaque, -1); found:    mpegts_close_filter(ts, ts->pat_filter);    ts->pat_filter = NULL;}/* add all services found in the PAT */static void pat_scan_cb(void *opaque, const uint8_t *section, int section_len){    MpegTSContext *ts = opaque;    SectionHeader h1, *h = &h1;    const uint8_t *p, *p_end;    int sid, pmt_pid;    char *provider_name, *name;    char buf[256];#ifdef DEBUG_SI    printf("PAT:\n");

⌨️ 快捷键说明

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