/* check if the provided BOS page is the start of a vorbis stream. If so * then setup a structure so it can be used */ ogg_codec_t *initial_vorbis_page (format_plugin_t *plugin, ogg_page *page) { ogg_state_t *ogg_info = plugin->_state; ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t)); ogg_packet packet; vorbis_codec_t *vorbis = calloc (1, sizeof (vorbis_codec_t)); ogg_stream_init (&codec->os, ogg_page_serialno (page)); ogg_stream_pagein (&codec->os, page); vorbis_info_init (&vorbis->vi); vorbis_comment_init (&vorbis->vc); ogg_stream_packetout (&codec->os, &packet); DEBUG0("checking for vorbis codec"); if (vorbis_synthesis_headerin (&vorbis->vi, &vorbis->vc, &packet) < 0) { ogg_stream_clear (&codec->os); vorbis_info_clear (&vorbis->vi); vorbis_comment_clear (&vorbis->vc); free (vorbis); free (codec); return NULL; } INFO0 ("seen initial vorbis header"); codec->specific = vorbis; codec->codec_free = vorbis_codec_free; codec->headers = 1; codec->parent = ogg_info; codec->name = "Vorbis"; free_ogg_packet (vorbis->header[0]); free_ogg_packet (vorbis->header[1]); free_ogg_packet (vorbis->header[2]); memset (vorbis->header, 0, sizeof (vorbis->header)); vorbis->header [0] = copy_ogg_packet (&packet); ogg_stream_init (&vorbis->new_os, rand()); codec->process_page = process_vorbis_page; codec->process = process_vorbis; plugin->set_tag = vorbis_set_tag; vorbis->bos_page.header = malloc (page->header_len + page->body_len); memcpy (vorbis->bos_page.header, page->header, page->header_len); vorbis->bos_page.header_len = page->header_len; vorbis->bos_page.body = vorbis->bos_page.header + page->header_len; memcpy (vorbis->bos_page.body, page->body, page->body_len); vorbis->bos_page.body_len = page->body_len; return codec; }
/* process the vorbis audio packets. Here we just take each packet out * and add them into the new stream, flushing after so many samples. We * also check if an new headers are requested after each processed page */ static int process_vorbis_audio (ogg_state_t *ogg_info, ogg_codec_t *codec) { vorbis_codec_t *source_vorbis = codec->specific; while (1) { int window; ogg_packet packet; /* now, lets extract what packets we can */ if (ogg_stream_packetout (&codec->os, &packet) <= 0) break; /* calculate granulepos for the packet */ window = vorbis_packet_blocksize (&source_vorbis->vi, &packet) / 4; source_vorbis->granulepos += window; if (source_vorbis->prev_packet) { ogg_packet *prev_packet = source_vorbis->prev_packet; add_audio_packet (source_vorbis, prev_packet); free_ogg_packet (prev_packet); packet . granulepos = source_vorbis->granulepos; } else { packet . granulepos = 0; } /* store the current packet details */ source_vorbis->prev_window = window; source_vorbis->prev_packet = copy_ogg_packet (&packet); if (packet.e_o_s) { initiate_flush (source_vorbis); free_ogg_packet (source_vorbis->prev_packet); source_vorbis->prev_packet = NULL; return 1; } /* allow for pages to be flushed if there's over a certain number of samples */ if (source_vorbis->samples_in_page > source_vorbis->page_samples_trigger) return 1; } if (source_vorbis->stream_notify) { initiate_flush (source_vorbis); source_vorbis->stream_notify = 0; return 1; } return -1; }
static void vorbis_codec_free (ogg_state_t *ogg_info, ogg_codec_t *codec) { vorbis_codec_t *vorbis = codec->specific; DEBUG0 ("freeing vorbis codec"); stats_event (ogg_info->mount, "audio_bitrate", NULL); stats_event (ogg_info->mount, "audio_channels", NULL); stats_event (ogg_info->mount, "audio_samplerate", NULL); vorbis_info_clear (&vorbis->vi); vorbis_comment_clear (&vorbis->vc); ogg_stream_clear (&codec->os); ogg_stream_clear (&vorbis->new_os); free_ogg_packet (vorbis->header[0]); free_ogg_packet (vorbis->header[1]); free_ogg_packet (vorbis->header[2]); free_ogg_packet (vorbis->prev_packet); free (vorbis->bos_page.header); free (vorbis); free (codec); }