static stream_processor *find_stream_processor(stream_set *set, ogg_page *page) { ogg_uint32_t serial = ogg_page_serialno(page); int i, found = 0; int invalid = 0; int constraint = 0; stream_processor *stream; for(i=0; i < set->used; i++) { if(serial == set->streams[i].serial) { /* We have a match! */ found = 1; stream = &(set->streams[i]); set->in_headers = 0; /* if we have detected EOS, then this can't occur here. */ if(stream->end) { stream->isillegal = 1; stream->constraint_violated = CONSTRAINT_PAGE_AFTER_EOS; return stream; } stream->isnew = 0; stream->start = ogg_page_bos(page); stream->end = ogg_page_eos(page); stream->serial = serial; return stream; } } /* If there are streams open, and we've reached the end of the * headers, then we can't be starting a new stream. * XXX: might this sometimes catch ok streams if EOS flag is missing, * but the stream is otherwise ok? */ if(streams_open(set) && !set->in_headers) { constraint = CONSTRAINT_MUXING_VIOLATED; invalid = 1; } set->in_headers = 1; if(set->allocated < set->used) stream = &set->streams[set->used]; else { set->allocated += 5; set->streams = realloc(set->streams, sizeof(stream_processor)* set->allocated); stream = &set->streams[set->used]; } set->used++; stream->num = set->used; /* We count from 1 */ stream->isnew = 1; stream->isillegal = invalid; stream->constraint_violated = constraint; { int res; ogg_packet packet; /* We end up processing the header page twice, but that's ok. */ ogg_stream_init(&stream->os, serial); ogg_stream_pagein(&stream->os, page); res = ogg_stream_packetout(&stream->os, &packet); if(res <= 0) { DPRINTF(E_WARN, L_SCAN, "Invalid header page, no packet found\n"); null_start(stream); } else if(packet.bytes >= 7 && memcmp(packet.packet, "\001vorbis", 7)==0) vorbis_start(stream); else if(packet.bytes >= 8 && memcmp(packet.packet, "OggMIDI\0", 8)==0) other_start(stream, "MIDI"); else other_start(stream, NULL); res = ogg_stream_packetout(&stream->os, &packet); if(res > 0) { DPRINTF(E_WARN, L_SCAN, "Invalid header page in stream %d, " "contains multiple packets\n", stream->num); } /* re-init, ready for processing */ ogg_stream_clear(&stream->os); ogg_stream_init(&stream->os, serial); } stream->start = ogg_page_bos(page); stream->end = ogg_page_eos(page); stream->serial = serial; /* if(stream->serial == 0 || stream->serial == -1) { info(_("Note: Stream %d has serial number %d, which is legal but may " "cause problems with some tools."), stream->num, stream->serial); }*/ return stream; }
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; }