BOOL ovd_parse_stream(ovd_stream_buf* buf) { ovd_handle* handle = (ovd_handle*)buf->handle; ogg_sync_wrote(handle->oy, buf->len); if (ogg_sync_pageout(handle->oy, &handle->og) != 1) goto fail; // ogg_stream_init(&handle->os, ogg_page_serialno(&handle->og)); handle->os = ogg_stream_create(ogg_page_serialno(&handle->og)); vorbis_info_init(&handle->vi); vorbis_comment_init(&handle->vc); if (ogg_stream_pagein(handle->os, &handle->og) < 0) goto fail; if (ogg_stream_packetout(handle->os,&handle->op) != 1) goto fail; if (vorbis_synthesis_headerin(&handle->vi, &handle->vc, &handle->op) < 0) goto fail; handle->init = 0; handle->eof = 0; ovd_header_init(handle); buf->buf = ogg_sync_bufferin(handle->oy, OVD_STREAM_BUF_LEN); buf->len = OVD_STREAM_BUF_LEN; return TRUE; fail: // ogg_sync_init(&handle->oy); handle->oy = ogg_sync_create(); buf->buf = ogg_sync_bufferin(handle->oy, OVD_STREAM_BUF_LEN); buf->len = OVD_STREAM_BUF_LEN; return FALSE; }
BOOL ovd_reparse_stream(ovd_stream_buf* buf) { ovd_handle* handle = (ovd_handle*)buf->handle; if (buf->len) { ogg_sync_wrote(handle->oy, buf->len); int result = ogg_sync_pageout(handle->oy, &handle->og); if (result == 0) { buf->len = OVD_STREAM_BUF_LEN; return TRUE; } else if (result < 0) return FALSE; } // ogg_stream_init(&handle->os, ogg_page_serialno(&handle->og)); handle->os = ogg_stream_create(ogg_page_serialno(&handle->og)); vorbis_info_init(&handle->vi); vorbis_comment_init(&handle->vc); if (ogg_stream_pagein(handle->os, &handle->og) < 0) return FALSE; if (ogg_stream_packetout(handle->os,&handle->op) != 1) return FALSE; if (vorbis_synthesis_headerin(&handle->vi, &handle->vc, &handle->op) < 0) return FALSE; handle->init = 0; handle->eof = 0; ovd_header_init(handle); buf->buf = ogg_sync_bufferin(handle->oy, OVD_STREAM_BUF_LEN); buf->len = OVD_STREAM_BUF_LEN; return TRUE; }
static int FillQueue(ogg* p,format_reader* Reader) { for (;;) { int Bytes = ogg_sync_pageseek(p->OggSync,&p->OggPage); if (Bytes == 0) // need more data { int Result; format_buffer* Buffer; if (!Reader->BufferAvailable && (!p->Format.SyncMode || p->Format.SyncRead<=0)) return ERR_NEED_MORE_DATA; Buffer = Format_BufferRemove(Reader); if (!Buffer && p->Format.SyncMode && p->Format.SyncRead>0 && Format_ReadBuffer(Reader,0)) Buffer = Format_BufferRemove(Reader); Result = AddBuffer(p,Buffer); if (Result != ERR_NONE) return Result; } else if (Bytes < 0) Reader->FilePos -= Bytes; else if (Bytes > 0) { int StreamNo; oggstream* s; int Id; Reader->FilePos += Bytes; Id = ogg_page_serialno(&p->OggPage); DEBUG_MSG4(DEBUG_FORMAT,T("OGG Page id:%d size:%d gran:%d filepos:%d"),Id,p->OggPage.body_len,(int)ogg_page_granulepos(&p->OggPage),Reader->FilePos - Bytes); for (StreamNo=0;StreamNo<p->Format.StreamCount;++StreamNo) if (p->Format.Streams[StreamNo]->Id == Id) break; if (StreamNo==p->Format.StreamCount) { // check for restarted audio http streaming (comments changed) if (p->Format.StreamCount==1 && p->Format.Streams[0]->Format.Type == PACKET_AUDIO && p->Format.Streams[0]->LastTime>0) { StreamNo = 0; s = (oggstream*) p->Format.Streams[0]; if (s->Vorbis) { // vorbis decoder have to release s->Info s->Stream.Format.Extra = NULL; s->Stream.Format.ExtraLength = 0; ConnectionUpdate((node*)&p->Format,FORMAT_STREAM+0,s->Stream.Pin.Node,s->Stream.Pin.No); } FreeStream(p,s); } else { s = (oggstream*) Format_AddStream(&p->Format,sizeof(oggstream)); if (!s) continue; } // init stream s->Stream.Id = Id; s->OggStream = ogg_stream_create(Id); s->NeedMorePage = 1; s->MediaTime = 0; s->Invalid = 0; s->Vorbis = 0; s->Native = 0; s->PacketNo = 0; vorbis_info_init(&s->Info); vorbis_comment_init(&s->Comment); } s = (oggstream*) p->Format.Streams[StreamNo]; if (s->Invalid) // drop invalid streams continue; if (s->PacketNo>=3) { if (!s->Stream.Pin.Node) // drop unused streams continue; if (p->Format.InSeek) { // reftime needed for SeekByPacket if ((s->MediaTime = ogg_page_granulepos(&p->OggPage)) != -1) { // no need for GlobalOffset here s->Stream.LastTime = (tick_t)(s->MediaTime * s->MediaRateDen / s->MediaRateNum); if (s->Stream.Format.Type == PACKET_AUDIO) { s->Stream.LastTime += p->Format.AVOffset; if (s->Stream.LastTime < 0) s->Stream.LastTime = 0; } } } } // add page to stream if (ogg_stream_pagein(s->OggStream,&p->OggPage) >= 0) { if (s->PacketNo<3) // header packet needed? { int i = ogg_stream_packetout(s->OggStream,&s->OggPacket); if (i == 0) // stream needs more pages continue; if (++s->PacketNo==1) // first packet? { ogg_reference* Ref; const void* Data; int Length; if (i < 0) { // first header packet is a must have s->Invalid = 1; continue; } if (p->Format.UseBufferBlock) { for (Length=0,Ref=s->OggPacket.packet;Ref;Ref=Ref->next) Length += Ref->length; if (s->Stream.BufferBlockLength<Length && !Format_AllocBufferBlock(&p->Format,&s->Stream,Length)) { Length = 0; Data = NULL; } else { for (Length=0,Ref=s->OggPacket.packet;Ref;Ref=Ref->next) { WriteBlock(&s->Stream.BufferBlock,Length,Ref->buffer->data + Ref->begin,Ref->length); Length += Ref->length; } Data = s->Stream.BufferBlock.Ptr; } } else { BufferDrop(&s->Stream.BufferMem); for (Ref=s->OggPacket.packet;Ref;Ref=Ref->next) BufferWrite(&s->Stream.BufferMem,Ref->buffer->data + Ref->begin, Ref->length, 16384); Data = s->Stream.BufferMem.Data; Length = s->Stream.BufferMem.WritePos; } if (OGMHeader(p,s,(char*)Data,Length) || SpeexHeader(p,s,(char*)Data,Length)) { PacketFormatDefault(&s->Stream.Format); s->PacketNo = 3; // no more headers } else if (!VorbisHeader(p,s)) { s->Invalid = 1; continue; } while (s->MediaRateNum > (1<<30)) { s->MediaRateDen >>= 1; s->MediaRateNum >>= 1; } Format_PrepairStream(&p->Format,&s->Stream); continue; } else { assert(s->Vorbis); // error in second or third header packet will not cause fatal error vorbis_synthesis_headerin(&s->Info,&s->Comment,&s->OggPacket); if (s->PacketNo == 3) { // got the three header packets: reinit codec with vorbis_info s->Stream.Format.Extra = &s->Info; s->Stream.Format.ExtraLength = -1; ConnectionUpdate((node*)&p->Format,FORMAT_STREAM+StreamNo,s->Stream.Pin.Node,s->Stream.Pin.No); SendComments(s); } continue; } }