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

📄 ogg2.c

📁 ffmpeg的完整源代码和作者自己写的文档。不但有在Linux的工程哦
💻 C
📖 第 1 页 / 共 2 页
字号:
        }

        os = ogg->streams + idx;

#if 0
        av_log (s, AV_LOG_DEBUG,
                "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
                idx, os->pstart, os->psize, os->segp, os->nsegs);
#endif

        if (!os->codec){
            if (os->header < 0){
                os->codec = ogg_find_codec (os->buf, os->bufpos);
                if (!os->codec){
                    os->header = 0;
                    return 0;
                }
            }else{
                return 0;
            }
        }

        segp = os->segp;
        psize = os->psize;

        while (os->segp < os->nsegs){
            int ss = os->segments[os->segp++];
            os->psize += ss;
            if (ss < 255){
                complete = 1;
                break;
            }
        }

        if (!complete && os->segp == os->nsegs){
            ogg->curidx = -1;
        }
    }while (!complete);

#if 0
    av_log (s, AV_LOG_DEBUG,
            "ogg_packet: idx %i, frame size %i, start %i\n",
            idx, os->psize, os->pstart);
#endif

    ogg->curidx = idx;

    if (os->header < 0){
        int hdr = os->codec->header (s, idx);
        if (!hdr){
          os->header = os->seq;
          os->segp = segp;
          os->psize = psize;
          ogg->headers = 1;
        }else{
          os->pstart += os->psize;
          os->psize = 0;
        }
    }

    if (os->header > -1 && os->seq > os->header){
        if (os->codec && os->codec->packet)
            os->codec->packet (s, idx);
        if (str)
            *str = idx;
        if (dstart)
            *dstart = os->pstart;
        if (dsize)
            *dsize = os->psize;
        os->pstart += os->psize;
        os->psize = 0;
    }

    os->seq++;
    if (os->segp == os->nsegs)
        ogg->curidx = -1;

    return 0;
}

static int
ogg_get_headers (AVFormatContext * s)
{
    ogg_t *ogg = s->priv_data;

    do{
        if (ogg_packet (s, NULL, NULL, NULL) < 0)
            return -1;
    }while (!ogg->headers);

#if 0
    av_log (s, AV_LOG_DEBUG, "found headers\n");
#endif

    return 0;
}

static uint64_t
ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
{
    ogg_t *ogg = s->priv_data;
    ogg_stream_t *os = ogg->streams + i;
    uint64_t pts = AV_NOPTS_VALUE;

    if(os->codec->gptopts){
        pts = os->codec->gptopts(s, i, gp);
    } else {
        pts = gp;
    }

    return pts;
}


static int
ogg_get_length (AVFormatContext * s)
{
    ogg_t *ogg = s->priv_data;
    int idx = -1, i;
    offset_t size, end;

    if(s->pb.is_streamed)
        return 0;

// already set
    if (s->duration != AV_NOPTS_VALUE)
        return 0;

    size = url_fsize(&s->pb);
    if(size < 0)
        return 0;
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;

    ogg_save (s);
    url_fseek (&s->pb, end, SEEK_SET);

    while (!ogg_read_page (s, &i)){
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
            ogg->streams[i].codec)
            idx = i;
    }

    if (idx != -1){
        s->streams[idx]->duration =
            ogg_gptopts (s, idx, ogg->streams[idx].granule);
    }

    ogg->size = size;
    ogg_restore (s, 0);
    ogg_save (s);
    while (!ogg_read_page (s, &i)) {
        if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
            break;
    }
    if (i == idx) {
        s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
        s->streams[idx]->duration -= s->streams[idx]->start_time;
    }
    ogg_restore (s, 0);

    return 0;
}


static int
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
{
    ogg_t *ogg = s->priv_data;
    ogg->curidx = -1;
    //linear headers seek from start
    if (ogg_get_headers (s) < 0){
      return -1;
    }

    //linear granulepos seek from end
    ogg_get_length (s);

    //fill the extradata in the per codec callbacks
    return 0;
}


static int
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
{
    ogg_t *ogg;
    ogg_stream_t *os;
    int idx = -1;
    int pstart, psize;

    //Get an ogg packet
    do{
        if (ogg_packet (s, &idx, &pstart, &psize) < 0)
            return AVERROR(EIO);
    }while (idx < 0 || !s->streams[idx]);

    ogg = s->priv_data;
    os = ogg->streams + idx;

    //Alloc a pkt
    if (av_new_packet (pkt, psize) < 0)
        return AVERROR(EIO);
    pkt->stream_index = idx;
    memcpy (pkt->data, os->buf + pstart, psize);
    if (os->lastgp != -1LL){
        pkt->pts = ogg_gptopts (s, idx, os->lastgp);
        os->lastgp = -1;
    }

    return psize;
}


static int
ogg_read_close (AVFormatContext * s)
{
    ogg_t *ogg = s->priv_data;
    int i;

    for (i = 0; i < ogg->nstreams; i++){
        av_free (ogg->streams[i].buf);
        av_free (ogg->streams[i].private);
    }
    av_free (ogg->streams);
    return 0;
}


static int
ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
               int flags)
{
    AVStream *st = s->streams[stream_index];
    ogg_t *ogg = s->priv_data;
    ByteIOContext *bc = &s->pb;
    uint64_t min = 0, max = ogg->size;
    uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
    int64_t pts = AV_NOPTS_VALUE;

    ogg_save (s);

    if ((uint64_t)target_ts < tmin || target_ts < 0)
        target_ts = tmin;
    while (min <= max && tmin < tmax){
        uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
        int i = -1;

        url_fseek (bc, p, SEEK_SET);

        while (!ogg_read_page (s, &i)){
            if (i == stream_index && ogg->streams[i].granule != 0 &&
                ogg->streams[i].granule != -1)
                break;
        }

        if (i == -1)
            break;

        pts = ogg_gptopts (s, i, ogg->streams[i].granule);
        p = url_ftell (bc);

        if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den)
            break;

        if (pts > target_ts){
            if (max == p && tmax == pts) {
                // probably our tmin is wrong, causing us to always end up too late in the file
                tmin = (target_ts + tmin + 1) / 2;
                if (tmin == target_ts) {
                    url_fseek(bc, min, SEEK_SET);
                    break;
                }
            }
            max = p;
            tmax = pts;
        }else{
            if (min == p && tmin == pts) {
                // probably our tmax is wrong, causing us to always end up too early in the file
                tmax = (target_ts + tmax) / 2;
                if (tmax == target_ts) {
                    url_fseek(bc, max, SEEK_SET);
                    break;
                }
            }
            min = p;
            tmin = pts;
        }
    }

    if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den){
        ogg_restore (s, 1);
        ogg_reset (ogg);
    }else{
        ogg_restore (s, 0);
        pts = AV_NOPTS_VALUE;
    }

    av_update_cur_dts(s, st, pts);
    return 0;

#if 0
    //later...
    int64_t pos;
    if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
        return -1;
    pos = url_ftell (&s->pb);
    ogg_read_timestamp (s, stream_index, &pos, pos - 1);
#endif

}

#if 0
static int64_t
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
                    int64_t pos_limit)
{
    ogg_t *ogg = s->priv_data;
    ByteIOContext *bc = &s->pb;
    int64_t pos, pts;

    if (*pos_arg < 0)
        return AV_NOPTS_VALUE;

    pos = *pos_arg;
}
#endif

static int ogg_probe(AVProbeData *p)
{
    if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
        p->buf[2] == 'g' && p->buf[3] == 'S' &&
        p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
        return AVPROBE_SCORE_MAX;
    else
        return 0;
}

AVInputFormat ogg_demuxer = {
    "ogg",
    "Ogg",
    sizeof (ogg_t),
    ogg_probe,
    ogg_read_header,
    ogg_read_packet,
    ogg_read_close,
    ogg_read_seek,
// ogg_read_timestamp,
    .extensions = "ogg",
};

⌨️ 快捷键说明

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