📄 ogg2.c
字号:
}
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 + -