static sf_count_t vorbis_length_aux (SF_PRIVATE * psf) { ogg_sync_state osync ; ogg_page page ; sf_count_t len = 0 ; stream_set *processors ; processors = create_stream_set () ; if (processors == NULL) return 0 ; // out of memory? ogg_sync_init (&osync) ; while (vorbis_length_get_next_page (psf, &osync, &page)) { stream_processor *p = find_stream_processor (processors, &page) ; if (!p) { len = 0 ; break ; } ; if (p->isillegal && !p->shownillegal) { p->shownillegal = 1 ; /* If it's a new stream, we want to continue processing this page ** anyway to suppress additional spurious errors */ if (!p->isnew) continue ; } ; if (!p->isillegal) { ogg_packet packet ; int header = 0 ; ogg_stream_pagein (&p->ostream, &page) ; if (p->doneheaders < 3) header = 1 ; while (ogg_stream_packetout (&p->ostream, &packet) > 0) { if (p->doneheaders < 3) { if (vorbis_synthesis_headerin (&p->vinfo, &p->vcomment, &packet) < 0) continue ; p->doneheaders ++ ; } ; } ; if (!header) { sf_count_t gp = ogg_page_granulepos (&page) ; if (gp > 0) p->lastgranulepos = gp ; } ; if (p->end) { vorbis_end (p, &len) ; p->isillegal = 1 ; } ; } ; } ; ogg_sync_clear (&osync) ; free_stream_set (processors, &len) ; return len ; } /* vorbis_length_aux */
static void free_stream_set (stream_set *set, sf_count_t * len) { int i ; for (i = 0 ; i < set->used ; i++) { if (!set->streams [i].end) vorbis_end (&set->streams [i], len) ; ogg_stream_clear (&set->streams [i].ostream) ; } ; free (set->streams) ; free (set) ; } /* free_stream_set */
void rip_ogg_process_chunk(RIP_MANAGER_INFO * rmi, LIST * page_list, const char *buf, u_long size, TRACK_INFO * ti) { OGG_PAGE_LIST *ol; int header; int ret; char *buffer; // static ogg_int64_t written = 0; // static unsigned int written = 0; // static int ogg_page2 = 0; INIT_LIST_HEAD(page_list); debug_printf("-- rip_ogg_process_chunk (%d)\n", size); buffer = ogg_sync_buffer(&rmi->ogg_sync, size); memcpy(buffer, buf, size); ogg_sync_wrote(&rmi->ogg_sync, size); do { switch (ret = ogg_sync_pageout(&rmi->ogg_sync, &rmi->ogg_pg)) { case -1: /* -1 if we were not properly synced and had to skip some bytes */ debug_printf("Hole in ogg, skipping bytes\n"); break; case 0: /* 0 if we need more data to verify a page */ debug_printf("Ogg needs more data\n"); break; case 1: /* 1 if we have a page */ debug_printf("Found an ogg page!\n"); /* Do stuff needed for decoding vorbis */ if (ogg_page_bos(&rmi->ogg_pg)) { int rc; ogg_packet packet; ogg_stream_init(&rmi->stream.os, ogg_page_serialno(&rmi->ogg_pg)); ogg_stream_pagein(&rmi->stream.os, &rmi->ogg_pg); rc = ogg_stream_packetout(&rmi->stream.os, &packet); if (rc <= 0) { printf("Warning: Invalid header page, no packet found\n"); // null_start (&rmi->stream); exit(1); } else if (packet.bytes >= 7 && memcmp(packet.packet, "\001vorbis", 7) == 0) { vorbis_start(&rmi->stream); } } header = vorbis_process(rmi, &rmi->stream, &rmi->ogg_pg, ti); if (ogg_page_eos(&rmi->ogg_pg)) { vorbis_end(&rmi->stream); } /* Create ogg page boundary struct */ ol = (OGG_PAGE_LIST *) malloc(sizeof(OGG_PAGE_LIST)); if (!ol) { printf("Malloc error\n"); exit(1); } ol->m_page_len = rmi->ogg_pg.header_len + rmi->ogg_pg.body_len; ol->m_page_flags = 0; /* ***************************************************** Create header buffer for relay stream. A pointer to the header buffer will attached to all pages after page 2. If a relay connects in the middle of a song, we send the header to the relay. Finally, the memory for the header is freed when the last page of the song is ejected from the cbuf. ** ***************************************************** */ if (ogg_page_bos(&rmi->ogg_pg)) { /* First page in song */ ol->m_page_flags |= OGG_PAGE_BOS; ol->m_header_buf_ptr = 0; ol->m_header_buf_len = 0; rmi->ogg_curr_header = (char *)malloc(ol->m_page_len); rmi->ogg_curr_header_len = ol->m_page_len; memcpy(rmi->ogg_curr_header, rmi->ogg_pg.header, rmi->ogg_pg.header_len); memcpy(rmi->ogg_curr_header + rmi->ogg_pg.header_len, rmi->ogg_pg.body, rmi->ogg_pg.body_len); } else if (header) { /* Second or third page in song */ ol->m_page_flags |= OGG_PAGE_2; ol->m_header_buf_ptr = 0; ol->m_header_buf_len = 0; rmi->ogg_curr_header = (char *) realloc(rmi->ogg_curr_header, rmi->ogg_curr_header_len + ol->m_page_len); memcpy(rmi->ogg_curr_header + rmi->ogg_curr_header_len, rmi->ogg_pg.header, rmi->ogg_pg.header_len); memcpy(rmi->ogg_curr_header + rmi->ogg_curr_header_len + rmi->ogg_pg.header_len, rmi->ogg_pg.body, rmi->ogg_pg.body_len); rmi->ogg_curr_header_len += ol->m_page_len; } else if (!ogg_page_eos(&rmi->ogg_pg)) { /* Middle pages in song */ ol->m_header_buf_ptr = rmi->ogg_curr_header; ol->m_header_buf_len = rmi->ogg_curr_header_len; } else { /* Last page in song */ ol->m_page_flags |= OGG_PAGE_EOS; ol->m_header_buf_ptr = rmi->ogg_curr_header; ol->m_header_buf_len = rmi->ogg_curr_header_len; rmi->ogg_curr_header = 0; rmi->ogg_curr_header_len = 0; } debug_printf("OGG_PAGE\n" " header_len = %d\n" " body_len = %d\n" " serial no = %d\n" " page no = %d\n" " bos? = %d\n" " eos? = %d\n", rmi->ogg_pg.header_len, rmi->ogg_pg.body_len, ogg_page_serialno(&rmi->ogg_pg), ogg_page_pageno(&rmi->ogg_pg), ogg_page_bos(&rmi->ogg_pg), ogg_page_eos(&rmi->ogg_pg)); list_add_tail(&(ol->m_list), page_list); break; } } while (ret != 0); debug_printf("OGG_SYNC state:\n" " storage = %d\n" " fill = %d\n" " returned = %d\n" " unsynced = %d\n" " headerbytes = %d\n" " bodybytes = %d\n", rmi->ogg_sync.storage, rmi->ogg_sync.fill, rmi->ogg_sync.returned, rmi->ogg_sync.unsynced, rmi->ogg_sync.headerbytes, rmi->ogg_sync.bodybytes); // return 1; }