Mercurial > hg > forks > bilotrip-mj12
diff liboggplayer-src/src/open_close.cpp @ 2:105513a2e3c9
Import liboggplayer source.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 05 Aug 2013 13:50:20 +0300 |
parents | |
children | 26ee741f8c08 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboggplayer-src/src/open_close.cpp Mon Aug 05 13:50:20 2013 +0300 @@ -0,0 +1,205 @@ +#include "imp.hpp" + + void OggPlayer::Imp::close() { + if(!need_close) return; + + if (vorbis_p) { + ogg_stream_clear(&o_vsstate); + vorbis_block_clear(&v_block); + vorbis_dsp_clear(&v_state); + } + vorbis_comment_clear(&v_comment); + vorbis_info_clear(&v_info); + + if (theora_p) { + ogg_stream_clear(&o_tsstate); + theora_clear(&t_state); + } + theora_comment_clear(&t_comment); + theora_info_clear(&t_info); + + ogg_sync_clear(&o_sync); + file_in.close(); + if (audio_buffer){ + delete[] audio_buffer; + audio_buffer = NULL; + } + need_close = false; + } + bool OggPlayer::Imp::parse_headers() { + int stateflag = 0; + while (!stateflag) { + if (!buffer_data()) + break; + while (ogg_sync_pageout(&o_sync, &o_page) > 0) { + ogg_stream_state test; + + /* is this a mandated initial header? If not, stop parsing */ + if (!ogg_page_bos(&o_page)) { + /* don't leak the page; get it into the appropriate stream */ + queue_page(&o_page); + stateflag = 1; + break; + } + + ogg_stream_init(&test, ogg_page_serialno(&o_page)); + ogg_stream_pagein(&test, &o_page); + ogg_stream_packetout(&test, &o_packet); + + /* identify the codec: try theora */ + if (!theora_p && theora_decode_header(&t_info, &t_comment, + &o_packet) >= 0) { + /* it is theora */ + memcpy(&o_tsstate, &test, sizeof(test)); + theora_p = 1; + } else if (!vorbis_p && vorbis_synthesis_headerin(&v_info, + &v_comment, &o_packet) >= 0) { + /* it is vorbis */ + memcpy(&o_vsstate, &test, sizeof(test)); + vorbis_p = 1; + } else { + /* whatever it is, we don't care about it */ + ogg_stream_clear(&test); + } + } + } + + // we're expecting more header packets. + while ((theora_p && theora_p < 3) || (vorbis_p && vorbis_p < 3)) { + int ret; + + // look for further theora headers + while (theora_p && (theora_p < 3) && (ret = ogg_stream_packetout( + &o_tsstate, &o_packet))) { + if (ret < 0) { + return false; + } + if (theora_decode_header(&t_info, &t_comment, &o_packet)) { + return false; + } + theora_p++; + } + + // look for more vorbis header packets + while (vorbis_p && (vorbis_p < 3) && (ret = ogg_stream_packetout( + &o_vsstate, &o_packet))) { + if (ret < 0) { + return false; + } + if (vorbis_synthesis_headerin(&v_info, &v_comment, &o_packet)) { + return false; + } + vorbis_p++; + if (vorbis_p == 3) + break; + } + + // The header pages/packets will arrive before anything else we + // care about, or the stream is not obeying spec + + if (ogg_sync_pageout(&o_sync, &o_page) > 0) { + queue_page(&o_page); /* demux into the appropriate stream */ + } else { + if (!buffer_data()) /* someone needs more data */{ + return false; + } + } + } + return true; + + } + + bool OggPlayer::Imp::init_decoders() { + if (theora_p) { + theora_decode_init(&t_state, &t_info); + theora_control(&t_state, TH_DECCTL_GET_PPLEVEL_MAX, &pp_level_max, + sizeof(pp_level_max)); + pp_level = pp_level_max; + theora_control(&t_state, TH_DECCTL_SET_PPLEVEL, &pp_level, + sizeof(pp_level)); + pp_inc = 0; + } else { + return false; + } + if (vorbis_p) { + vorbis_synthesis_init(&v_state, &v_info); + vorbis_block_init(&v_state, &v_block); + } else { + return false; + } + return true; + } + + void OggPlayer::Imp::open(std::string path, AudioFormat audio_format, int channels, + int rate, VideoFormat video_format) { + + theora_p = 0; + vorbis_p = 0; + videobuf_ready = false; + frame=0; + last_frame_read=0; + + // 1) open the input file + file_in.open(path.c_str(), std::ios::binary); + if (file_in.fail()) { + failbit = true; + return; + } + + // 2) init some structs + ogg_sync_init(&o_sync); + vorbis_info_init(&v_info); + vorbis_comment_init(&v_comment); + theora_info_init(&t_info); + theora_comment_init(&t_comment); + + // 3) parse headers + if (!failbit && !parse_headers()) { + failbit = true; + } + + // 3) init decoders + if (!failbit && !init_decoders()) { + failbit = true; + } + + // 4) if fail, tear down the partial setup + if (failbit) { + theora_info_clear(&t_info); + theora_comment_clear(&t_comment); + vorbis_info_clear(&v_info); + vorbis_comment_clear(&v_comment); + ogg_sync_clear(&o_sync); + file_in.close(); + return; + } + + // 5) init audio conversion + int ret = SDL_BuildAudioCVT(&cvt, AUDIO_S16, v_info.channels, + v_info.rate, audio_format, channels, rate); + if (-1 == ret) { + failbit = true; + return; + } + // play() will allocate memory when needed + audio_buffer_size = 0; + audio_buffer = NULL; + + switch(video_format){ + //pixel_format.set(r_offset,g_offset,b_offset,bpp not a_offset); + case VF_RGB: + pixel_format.set(0,1,2,3); + break; + case VF_BGR: + pixel_format.set(2,1,0,3); + break; + case VF_RGBA: + pixel_format.set(0,1,2,4); + break; + case VF_BGRA: + pixel_format.set(2,1,0,4); + break; + } + need_close = true; + } +