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

📄 mpegts.c

📁 arm平台下的H264编码和解码源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    }    return 0;}static int mpegts_probe(AVProbeData *p){#if 1    const int size= p->buf_size;    int score, fec_score;#define CHECK_COUNT 10        if (size < (TS_FEC_PACKET_SIZE * CHECK_COUNT))        return -1;        score    = analyze(p->buf, TS_PACKET_SIZE    *CHECK_COUNT, TS_PACKET_SIZE, NULL);    fec_score= analyze(p->buf, TS_FEC_PACKET_SIZE*CHECK_COUNT, TS_FEC_PACKET_SIZE, NULL);//    av_log(NULL, AV_LOG_DEBUG, "score: %d, fec_score: %d \n", score, fec_score);  // we need a clear definition for the returned score otherwise things will become messy sooner or later    if     (score > fec_score && score > 6) return AVPROBE_SCORE_MAX + score     - CHECK_COUNT;    else if(                 fec_score > 6) return AVPROBE_SCORE_MAX + fec_score - CHECK_COUNT;    else                                    return -1;#else    /* only use the extension for safer guess */    if (match_ext(p->filename, "ts"))        return AVPROBE_SCORE_MAX;    else        return 0;#endif}void set_service_cb(void *opaque, int ret){    MpegTSContext *ts = opaque;    ts->set_service_ret = ret;    ts->stop_parse = 1;}/* return the 90 kHz PCR and the extension for the 27 MHz PCR. return   (-1) if not available */static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,                      const uint8_t *packet){    int afc, len, flags;    const uint8_t *p;    unsigned int v;    afc = (packet[3] >> 4) & 3;    if (afc <= 1)        return -1;    p = packet + 4;    len = p[0];    p++;    if (len == 0)        return -1;    flags = *p++;    len--;    if (!(flags & 0x10))        return -1;    if (len < 6)        return -1;    v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];    *ppcr_high = ((int64_t)v << 1) | (p[4] >> 7);    *ppcr_low = ((p[4] & 1) << 8) | p[5];    return 0;}static int mpegts_read_header(AVFormatContext *s,                              AVFormatParameters *ap){    MpegTSContext *ts = s->priv_data;    ByteIOContext *pb = &s->pb;    uint8_t buf[1024];    int len, sid;    int64_t pos;    MpegTSService *service;        if (ap) {        ts->mpeg2ts_raw = ap->mpeg2ts_raw;        ts->mpeg2ts_compute_pcr = ap->mpeg2ts_compute_pcr;    }    /* read the first 1024 bytes to get packet size */    pos = url_ftell(pb);    len = get_buffer(pb, buf, sizeof(buf));    if (len != sizeof(buf))        goto fail;    ts->raw_packet_size = get_packet_size(buf, sizeof(buf));    if (ts->raw_packet_size <= 0)        goto fail;    ts->stream = s;    ts->auto_guess = 0;    if (!ts->mpeg2ts_raw) {        /* normal demux */        if (!ts->auto_guess) {            ts->set_service_ret = -1;            /* first do a scaning to get all the services */            url_fseek(pb, pos, SEEK_SET);            mpegts_scan_sdt(ts);                        handle_packets(ts, MAX_SCAN_PACKETS);                        if (ts->nb_services <= 0) {                /* no SDT found, we try to look at the PAT */                                /* First remove the SDT filters from each PID */                int i;                for (i=0; i < NB_PID_MAX; i++) {                    if (ts->pids[i])                        mpegts_close_filter(ts, ts->pids[i]);                }                url_fseek(pb, pos, SEEK_SET);                mpegts_scan_pat(ts);                                handle_packets(ts, MAX_SCAN_PACKETS);            }                        if (ts->nb_services <= 0) {		/* raw transport stream */		ts->auto_guess = 1;		s->ctx_flags |= AVFMTCTX_NOHEADER;		goto do_pcr;	    }                        /* tune to first service found */            service = ts->services[0];            sid = service->sid;#ifdef DEBUG_SI            printf("tuning to '%s'\n", service->name);#endif                        /* now find the info for the first service if we found any,               otherwise try to filter all PATs */                        url_fseek(pb, pos, SEEK_SET);            mpegts_set_service(ts, sid, set_service_cb, ts);                        handle_packets(ts, MAX_SCAN_PACKETS);                        /* if could not find service, exit */            if (ts->set_service_ret != 0)                return -1;            #ifdef DEBUG_SI            printf("tuning done\n");#endif        }        s->ctx_flags |= AVFMTCTX_NOHEADER;    } else {        AVStream *st;        int pcr_pid, pid, nb_packets, nb_pcrs, ret, pcr_l;        int64_t pcrs[2], pcr_h;        int packet_count[2];        uint8_t packet[TS_PACKET_SIZE];                /* only read packets */        s->pts_num = 1;        s->pts_den = 27000000;            do_pcr:        st = av_new_stream(s, 0);        if (!st)            goto fail;        st->codec.codec_type = CODEC_TYPE_DATA;        st->codec.codec_id = CODEC_ID_MPEG2TS;                /* we iterate until we find two PCRs to estimate the bitrate */        pcr_pid = -1;        nb_pcrs = 0;        nb_packets = 0;        for(;;) {            ret = read_packet(&s->pb, packet, ts->raw_packet_size);            if (ret < 0)                return -1;            pid = ((packet[1] & 0x1f) << 8) | packet[2];            if ((pcr_pid == -1 || pcr_pid == pid) &&                parse_pcr(&pcr_h, &pcr_l, packet) == 0) {                pcr_pid = pid;                packet_count[nb_pcrs] = nb_packets;                pcrs[nb_pcrs] = pcr_h * 300 + pcr_l;                nb_pcrs++;                if (nb_pcrs >= 2)                    break;            }            nb_packets++;        }        ts->pcr_pid = pcr_pid;        /* NOTE1: the bitrate is computed without the FEC */        /* NOTE2: it is only the bitrate of the start of the stream */        ts->pcr_incr = (pcrs[1] - pcrs[0]) / (packet_count[1] - packet_count[0]);        ts->cur_pcr = pcrs[0] - ts->pcr_incr * packet_count[0];        s->bit_rate = (TS_PACKET_SIZE * 8) * 27e6 / ts->pcr_incr;        st->codec.bit_rate = s->bit_rate;        st->start_time = ts->cur_pcr * 1000000.0 / 27.0e6;#if 0        printf("start=%0.3f pcr=%0.3f incr=%d\n",               st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr);#endif    }    url_fseek(pb, pos, SEEK_SET);    return 0; fail:    return -1;}#define MAX_PACKET_READAHEAD ((128 * 1024) / 188)static int mpegts_raw_read_packet(AVFormatContext *s,                                  AVPacket *pkt){    MpegTSContext *ts = s->priv_data;    int ret, i;    int64_t pcr_h, next_pcr_h, pos;    int pcr_l, next_pcr_l;    uint8_t pcr_buf[12];    if (av_new_packet(pkt, TS_PACKET_SIZE) < 0)        return -ENOMEM;    ret = read_packet(&s->pb, pkt->data, ts->raw_packet_size);    if (ret < 0) {        av_free_packet(pkt);        return ret;    }    if (ts->mpeg2ts_compute_pcr) {        /* compute exact PCR for each packet */        if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) {            /* we read the next PCR (XXX: optimize it by using a bigger buffer */            pos = url_ftell(&s->pb);            for(i = 0; i < MAX_PACKET_READAHEAD; i++) {                url_fseek(&s->pb, pos + i * ts->raw_packet_size, SEEK_SET);                get_buffer(&s->pb, pcr_buf, 12);                if (parse_pcr(&next_pcr_h, &next_pcr_l, pcr_buf) == 0) {                    /* XXX: not precise enough */                    ts->pcr_incr = ((next_pcr_h - pcr_h) * 300 + (next_pcr_l - pcr_l)) /                         (i + 1);                    break;                }            }            url_fseek(&s->pb, pos, SEEK_SET);            /* no next PCR found: we use previous increment */            ts->cur_pcr = pcr_h * 300 + pcr_l;        }        pkt->pts = ts->cur_pcr;        pkt->duration = ts->pcr_incr;        ts->cur_pcr += ts->pcr_incr;    }    pkt->stream_index = 0;    return 0;}static int mpegts_read_packet(AVFormatContext *s,                              AVPacket *pkt){    MpegTSContext *ts = s->priv_data;    if (!ts->mpeg2ts_raw) {        ts->pkt = pkt;        return handle_packets(ts, 0);    } else {        return mpegts_raw_read_packet(s, pkt);    }}static int mpegts_read_close(AVFormatContext *s){    MpegTSContext *ts = s->priv_data;    int i;    for(i=0;i<NB_PID_MAX;i++)        if (ts->pids[i]) mpegts_close_filter(ts, ts->pids[i]);    return 0;}static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,                               int64_t *ppos, int find_next){    MpegTSContext *ts = s->priv_data;    int64_t pos, timestamp;    uint8_t buf[TS_PACKET_SIZE];    int pcr_l, pid;    pos = *ppos;    if (find_next) {        for(;;) {            url_fseek(&s->pb, pos, SEEK_SET);            if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)                return AV_NOPTS_VALUE;            pid = ((buf[1] & 0x1f) << 8) | buf[2];            if (pid == ts->pcr_pid &&                parse_pcr(&timestamp, &pcr_l, buf) == 0) {                break;            }            pos += ts->raw_packet_size;        }    } else {        for(;;) {            pos -= ts->raw_packet_size;            if (pos < 0)                return AV_NOPTS_VALUE;            url_fseek(&s->pb, pos, SEEK_SET);            if (get_buffer(&s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE)                return AV_NOPTS_VALUE;            pid = ((buf[1] & 0x1f) << 8) | buf[2];            if (pid == ts->pcr_pid &&                parse_pcr(&timestamp, &pcr_l, buf) == 0) {                break;            }        }    }    *ppos = pos;    return timestamp;}typedef int64_t ReadTimestampFunc(AVFormatContext *s, int stream_index,                                   int64_t *ppos, int find_next);static int64_t do_block_align(int64_t val, int block_align){    return (val / block_align) * block_align;}/* XXX: use it in other formats */static int timestamp_read_seek(AVFormatContext *s,                                int stream_index, int64_t timestamp,                               ReadTimestampFunc *read_timestamp,                               int block_align){    int64_t pos_min, pos_max, pos;    int64_t dts_min, dts_max, dts;#ifdef DEBUG_SEEK    printf("read_seek: %d %0.3f\n", stream_index, timestamp / 90000.0);#endif    pos_min = 0;    dts_min = read_timestamp(s, stream_index, &pos_min, 1);    if (dts_min == AV_NOPTS_VALUE) {        /* we can reach this case only if no PTS are present in           the whole stream */        return -1;    }    pos_max = do_block_align(url_filesize(url_fileno(&s->pb)), block_align) -         block_align;    dts_max = read_timestamp(s, stream_index, &pos_max, 0);        while (pos_min <= pos_max) {#ifdef DEBUG_SEEK        printf("pos_min=0x%llx pos_max=0x%llx dts_min=%0.3f dts_max=%0.3f\n",                pos_min, pos_max,               dts_min / 90000.0, dts_max / 90000.0);#endif        if (timestamp <= dts_min) {            pos = pos_min;            goto found;        } else if (timestamp >= dts_max) {            pos = pos_max;            goto found;        } else {            /* interpolate position (better than dichotomy) */            pos = (int64_t)((double)(pos_max - pos_min) *                             (double)(timestamp - dts_min) /                            (double)(dts_max - dts_min)) + pos_min;            pos = do_block_align(pos, block_align);        }#ifdef DEBUG_SEEK        printf("pos=0x%llx\n", pos);#endif        /* read the next timestamp */        dts = read_timestamp(s, stream_index, &pos, 1);        /* check if we are lucky */        if (dts == AV_NOPTS_VALUE) {            /* should never happen */            pos = pos_min;            goto found;        } else if (timestamp == dts) {            goto found;        } else if (timestamp < dts) {            pos_max = pos;            dts_max = read_timestamp(s, stream_index, &pos_max, 0);            if (dts_max == AV_NOPTS_VALUE) {                /* should never happen */                break;            } else if (timestamp >= dts_max) {                pos = pos_max;                goto found;            }        } else {            pos_min = pos + block_align;            dts_min = read_timestamp(s, stream_index, &pos_min, 1);            if (dts_min == AV_NOPTS_VALUE) {                /* should never happen */                goto found;            } else if (timestamp <= dts_min) {                goto found;            }        }    }    pos = pos_min; found:#ifdef DEBUG_SEEK    pos_min = pos;    dts_min = read_timestamp(s, stream_index, &pos_min, 1);    pos_min += block_align;    dts_max = read_timestamp(s, stream_index, &pos_min, 1);    printf("pos=0x%llx %0.3f<=%0.3f<=%0.3f\n",            pos, dts_min / 90000.0, timestamp / 90000.0, dts_max / 90000.0);#endif    /* do the seek */    url_fseek(&s->pb, pos, SEEK_SET);    return 0;}static int mpegts_read_seek(AVFormatContext *s,                             int stream_index, int64_t timestamp){    MpegTSContext *ts = s->priv_data;    timestamp = (timestamp * 90000) / AV_TIME_BASE;    return timestamp_read_seek(s, stream_index, timestamp,                                mpegts_get_pcr, ts->raw_packet_size);}/**************************************************************//* parsing functions - called from other demuxers such as RTP */MpegTSContext *mpegts_parse_open(AVFormatContext *s){    MpegTSContext *ts;        ts = av_mallocz(sizeof(MpegTSContext));    if (!ts)        return NULL;    /* no stream case, currently used by RTP */    ts->raw_packet_size = TS_PACKET_SIZE;    ts->stream = s;    ts->auto_guess = 1;    return ts;}/* return the consumed length if a packet was output, or -1 if no   packet is output */int mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,                        const uint8_t *buf, int len){    int len1;    len1 = len;    ts->pkt = pkt;    ts->stop_parse = 0;    for(;;) {        if (ts->stop_parse)            break;        if (len < TS_PACKET_SIZE)            return -1;        if (buf[0] != 0x47) {            buf++;            len--;        } else {            handle_packet(ts, buf);            buf += TS_PACKET_SIZE;            len -= TS_PACKET_SIZE;        }    }    return len1 - len;}void mpegts_parse_close(MpegTSContext *ts){    int i;    for(i=0;i<NB_PID_MAX;i++)        av_free(ts->pids[i]);    av_free(ts);}AVInputFormat mpegts_demux = {    "mpegts",    "MPEG2 transport stream format",    sizeof(MpegTSContext),    mpegts_probe,    mpegts_read_header,    mpegts_read_packet,    mpegts_read_close,    mpegts_read_seek,    .flags = AVFMT_SHOW_IDS,};int mpegts_init(void){    av_register_input_format(&mpegts_demux);#ifdef CONFIG_ENCODERS    av_register_output_format(&mpegts_mux);#endif    return 0;}

⌨️ 快捷键说明

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