📄 libovd.cpp
字号:
int result = ogg_sync_pageout(&handle->oy, &handle->og);
if (result == 0)
return FALSE; // need more data
if (result == 1) {
ogg_stream_pagein(&handle->os, &handle->og);
while(handle->init < 2){
result = ogg_stream_packetout(&handle->os, &handle->op);
if (result == 0)
return 0; // need more data
if (result < 0) {
handle->init = -1; // fatal error
return -1;
}
vorbis_synthesis_headerin(&handle->vi, &handle->vc, &handle->op);
handle->init++;
}
}
else if (result = -1) return -1;
}
vorbis_synthesis_init(&handle->vd, &handle->vi);
vorbis_block_init(&handle->vd, &handle->vb);
return 1;
}
return 1;
}
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));
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_buffer(&handle->oy, OVD_STREAM_BUF_LEN);
buf->len = OVD_STREAM_BUF_LEN;
return TRUE;
fail:
ogg_sync_init(&handle->oy);
buf->buf = ogg_sync_buffer(&handle->oy, OVD_STREAM_BUF_LEN);
buf->len = OVD_STREAM_BUF_LEN;
return FALSE;
}
BOOL ovd_get_stream_info(ovd_stream_buf* buf, ovd_info* info)
{
ovd_handle* handle = (ovd_handle*)buf->handle;
info->version = handle->vi.version;
info->rate = handle->vi.rate;
info->channels = handle->vi.channels;
info->bitrate_lower = handle->vi.bitrate_lower;
info->bitrate_nominal = handle->vi.bitrate_nominal;
info->bitrate_upper = handle->vi.bitrate_upper;
info->bitrate_window = handle->vi.bitrate_window;
return TRUE;
}
BOOL ovd_get_stream_comment(ovd_stream_buf* buf, ovd_comment* comment)
{
ovd_handle* handle = (ovd_handle*)buf->handle;
memset(comment, 0, sizeof(ovd_comment));
for (int i = 0; i < handle->vc.comments; i++)
{
LPTSTR psz = NULL;
char* s = strchr(handle->vc.user_comments[i], '=');
if (s)
{
*s = NULL;
ovd_strupr(handle->vc.user_comments[i]);
if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_DATE) == 0)
psz = comment->szDate;
else if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_TRACKNUM) == 0)
psz = comment->szTrackNum;
else if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_TITLE) == 0)
psz = comment->szTitle;
else if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_ARTIST) == 0)
psz = comment->szArtist;
else if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_ALBUM) == 0)
psz = comment->szAlbum;
else if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_GENRE) == 0)
psz = comment->szGenre;
else if (strcmp(handle->vc.user_comments[i], OVD_COMMENT_COMMENT) == 0)
psz = comment->szComment;
if (psz)
{
#ifdef _UNICODE
UTF8toUCS2(s + 1, psz, OVD_COMMENT_LEN);
#else
WCHAR sz[OVD_COMMENT_LEN];
UTF8toUCS2(s + 1, sz, OVD_COMMENT_LEN);
WideCharToMultiByte(CP_ACP, 0, sz, -1, psz, OVD_COMMENT_LEN, 0, 0);
#endif
}
}
}
return TRUE;
}
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));
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_buffer(&handle->oy, OVD_STREAM_BUF_LEN);
buf->len = OVD_STREAM_BUF_LEN;
return TRUE;
}
int ovd_decode_stream(ovd_stream_buf* buf, LPBYTE pcmbuf, int pcmbuf_len, int* pcmout)
{
int result, samples, ret = OVD_OK;
ovd_handle* handle = (ovd_handle*)buf->handle;
*pcmout = 0;
if (handle->samples) {
if (pcmbuf_len < handle->samples * handle->vi.channels * 2) {
buf->len = 0;
return OVD_NEED_MORE_OUTPUT;
}
for (int i = 0; i < handle->vi.channels; i++) {
ogg_int32_t* src = handle->pcm[i];
short* dest = ((short *)(pcmbuf + *pcmout)) + i;
for (int j = 0; j < handle->samples; j++) {
*dest = CLIP_TO_15(src[j] >> 9);
dest += handle->vi.channels;
}
}
vorbis_synthesis_read(&handle->vd, handle->samples);
*pcmout += handle->samples * handle->vi.channels * 2;
pcmbuf_len -= handle->samples * handle->vi.channels * 2;
handle->samples = 0;
}
if (handle->eof) {
if (!ovd_reparse_stream(buf))
return OVD_FATAL_ERR;
goto done;
}
if (buf->len) {
ogg_sync_wrote(&handle->oy, buf->len);
buf->len = OVD_STREAM_BUF_LEN;
result = ovd_header_init(handle);
if (result != 1) {
if (result < 0)
ret = OVD_FATAL_ERR;
goto done;
}
result = ogg_sync_pageout(&handle->oy, &handle->og);
if (result == 0)
goto done; // need more
if (result < 0) {
ret = OVD_FATAL_ERR;
handle->init = -1;
goto done;
}
ogg_stream_pagein(&handle->os, &handle->og);
while (1) {
result = ogg_stream_packetout(&handle->os, &handle->op);
if (result == 0)
break;
if (result > 0) {
if (vorbis_synthesis(&handle->vb, &handle->op) == 0)
vorbis_synthesis_blockin(&handle->vd, &handle->vb);
vorbis_synthesis_headerin(&handle->vi, &handle->vc, &handle->op);
while ((samples = vorbis_synthesis_pcmout(&handle->vd, &handle->pcm)) > 0) {
if (pcmbuf_len < samples * handle->vi.channels * 2) {
handle->samples = samples;
buf->len = 0;
return OVD_NEED_MORE_OUTPUT;
}
for (int i = 0; i < handle->vi.channels; i++) {
ogg_int32_t* src = handle->pcm[i];
short* dest = ((short *)(pcmbuf + *pcmout)) + i;
for (int j = 0; j < samples; j++) {
*dest = CLIP_TO_15(src[j] >> 9);
dest += handle->vi.channels;
}
}
vorbis_synthesis_read(&handle->vd, samples);
*pcmout += samples * handle->vi.channels * 2;
pcmbuf_len -= samples * handle->vi.channels * 2;
handle->samples = 0;
}
}
}
}
else {
result = 1;
buf->len = OVD_STREAM_BUF_LEN;
while (1) {
if (result > 0) {
while ((samples = vorbis_synthesis_pcmout(&handle->vd, &handle->pcm)) > 0) {
if (pcmbuf_len < samples * handle->vi.channels * 2) {
handle->samples = samples;
buf->len = 0;
return OVD_NEED_MORE_OUTPUT;
}
for (int i = 0; i < handle->vi.channels; i++) {
ogg_int32_t* src = handle->pcm[i];
short* dest = ((short *)(pcmbuf + *pcmout)) + i;
for (int j = 0; j < samples; j++) {
*dest = CLIP_TO_15(src[j] >> 9);
dest += handle->vi.channels;
}
}
vorbis_synthesis_read(&handle->vd, samples);
*pcmout += samples * handle->vi.channels * 2;
pcmbuf_len -= samples * handle->vi.channels * 2;
handle->samples = 0;
}
}
result = ogg_stream_packetout(&handle->os, &handle->op);
if (result == 0)
break;
if (result > 0) {
if (vorbis_synthesis(&handle->vb, &handle->op) == 0)
vorbis_synthesis_blockin(&handle->vd, &handle->vb);
vorbis_synthesis_headerin(&handle->vi, &handle->vc, &handle->op);
}
}
}
if (ogg_page_eos(&handle->og)) {
handle->samples = 0;
handle->init = 0;
ogg_stream_clear(&handle->os);
vorbis_block_clear(&handle->vb);
vorbis_dsp_clear(&handle->vd);
vorbis_comment_clear(&handle->vc);
vorbis_info_clear(&handle->vi); /* must be called last */
handle->eof = 1;
buf->len = OVD_STREAM_BUF_LEN;
}
done:
if (buf->len) buf->buf = ogg_sync_buffer(&handle->oy, OVD_STREAM_BUF_LEN);
return ret;
}
void ovd_uninit_stream(ovd_stream_buf* buf)
{
ovd_handle* handle = (ovd_handle*)buf->handle;
vorbis_block_clear(&handle->vb);
vorbis_dsp_clear(&handle->vd);
vorbis_comment_clear(&handle->vc);
vorbis_info_clear(&handle->vi);
ogg_sync_clear(&handle->oy);
delete handle;
delete buf;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -