📄 demux_ogg.c
字号:
ogg_sync_init(sync); while(1) { /// Try to get a page ogg_d->pos += ogg_d->last_size; np = ogg_sync_pageseek(sync,page); /// Error if(np < 0) { mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg demuxer : Bad page sync\n"); goto err_out; } /// Need some more data if(np == 0) { int len; buf = ogg_sync_buffer(sync,BLOCK_SIZE); len = stream_read(s,buf,BLOCK_SIZE); if(len == 0 && s->eof) { goto err_out; } ogg_sync_wrote(sync,len); continue; } ogg_d->last_size = np; // We got one page now if( ! ogg_page_bos(page) ) { // It's not a begining page // Header parsing end here, we need to get the page otherwise it will be lost int id = demux_ogg_get_page_stream(ogg_d,NULL); if(id >= 0) ogg_stream_pagein(&ogg_d->subs[id].stream,page); else mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg : Warning found none bos page from unknown stream %d\n",ogg_page_serialno(page)); break; } /// Init the data structure needed for a logical stream ogg_d->subs = (ogg_stream_t*)realloc(ogg_d->subs,(ogg_d->num_sub+1)*sizeof(ogg_stream_t)); memset(&ogg_d->subs[ogg_d->num_sub],0,sizeof(ogg_stream_t)); /// Get the stream serial number s_no = ogg_page_serialno(page); ogg_stream_init(&ogg_d->subs[ogg_d->num_sub].stream,s_no); mp_msg(MSGT_DEMUX,MSGL_DBG2,"Ogg : Found a stream with serial=%d\n",s_no); // Take the first page ogg_stream_pagein(&ogg_d->subs[ogg_d->num_sub].stream,page); // Get first packet of the page ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack); // Reset our vars sh_a = NULL; sh_v = NULL; demux_aid_vid_mismatch = 1; // don't identify in new_sh_* since ids don't match // Check for Vorbis if(pack.bytes >= 7 && ! strncmp(&pack.packet[1],"vorbis", 6) ) { sh_a = new_sh_audio(demuxer,ogg_d->num_sub); sh_a->format = FOURCC_VORBIS; ogg_d->subs[ogg_d->num_sub].vorbis = 1; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", n_audio); ogg_d->subs[ogg_d->num_sub].id = n_audio; n_audio++; mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (Vorbis), -aid %d\n",ogg_d->num_sub,n_audio-1); // check for Theora# ifdef HAVE_OGGTHEORA } else if (pack.bytes >= 7 && !strncmp (&pack.packet[1], "theora", 6)) { int errorCode = 0; theora_info inf; theora_comment cc; theora_info_init (&inf); theora_comment_init (&cc); errorCode = theora_decode_header (&inf, &cc, &pack); if (errorCode) mp_msg(MSGT_DEMUX,MSGL_ERR,"Theora header parsing failed: %i \n", errorCode); else { sh_v = new_sh_video(demuxer,ogg_d->num_sub); sh_v->context = NULL; sh_v->bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER)); sh_v->bih->biSize=sizeof(BITMAPINFOHEADER); sh_v->bih->biCompression= sh_v->format = FOURCC_THEORA; sh_v->fps = ((double)inf.fps_numerator)/ (double)inf.fps_denominator; sh_v->frametime = ((double)inf.fps_denominator)/ (double)inf.fps_numerator; sh_v->disp_w = sh_v->bih->biWidth = inf.frame_width; sh_v->disp_h = sh_v->bih->biHeight = inf.frame_height; sh_v->bih->biBitCount = 24; sh_v->bih->biPlanes = 3; sh_v->bih->biSizeImage = ((sh_v->bih->biBitCount/8) * sh_v->bih->biWidth*sh_v->bih->biHeight); ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps; ogg_d->subs[ogg_d->num_sub].theora = 1; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VIDEO_ID=%d\n", n_video); ogg_d->subs[ogg_d->num_sub].id = n_video; n_video++; mp_msg(MSGT_DEMUX,MSGL_INFO, "[Ogg] stream %d: video (Theora v%d.%d.%d), -vid %d\n", ogg_d->num_sub, (int)inf.version_major, (int)inf.version_minor, (int)inf.version_subminor, n_video - 1); if(verbose>0) print_video_header(sh_v->bih); }# endif /* HAVE_OGGTHEORA */# ifdef HAVE_FLAC } else if (pack.bytes >= 4 && !strncmp (&pack.packet[0], "fLaC", 4)) { sh_a = new_sh_audio(demuxer,ogg_d->num_sub); sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", n_audio); ogg_d->subs[ogg_d->num_sub].id = n_audio; n_audio++; ogg_d->subs[ogg_d->num_sub].flac = 1; sh_a->wf = NULL; mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (FLAC), -aid %d\n",ogg_d->num_sub,n_audio-1);# endif /* HAVE_FLAC */ /// Check for old header } else if(pack.bytes >= 142 && ! strncmp(&pack.packet[1],"Direct Show Samples embedded in Ogg",35) ) { // Old video header if(get_uint32 (pack.packet+96) == 0x05589f80 && pack.bytes >= 184) { sh_v = new_sh_video(demuxer,ogg_d->num_sub); sh_v->bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER)); sh_v->bih->biSize=sizeof(BITMAPINFOHEADER); sh_v->bih->biCompression= sh_v->format = mmioFOURCC(pack.packet[68],pack.packet[69], pack.packet[70],pack.packet[71]); sh_v->frametime = get_uint64(pack.packet+164)*0.0000001; sh_v->fps = 1/sh_v->frametime; sh_v->disp_w = sh_v->bih->biWidth = get_uint32(pack.packet+176); sh_v->disp_h = sh_v->bih->biHeight = get_uint32(pack.packet+180); sh_v->bih->biBitCount = get_uint16(pack.packet+182); if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME sh_v->bih->biPlanes=1; sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight; ogg_d->subs[ogg_d->num_sub].samplerate = sh_v->fps; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VIDEO_ID=%d\n", n_video); ogg_d->subs[ogg_d->num_sub].id = n_video; n_video++; mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n", ogg_d->num_sub,pack.packet[68],pack.packet[69],pack.packet[70],pack.packet[71],n_video-1); if(verbose>0) print_video_header(sh_v->bih); // Old audio header } else if(get_uint32(pack.packet+96) == 0x05589F81) { unsigned int extra_size; sh_a = new_sh_audio(demuxer,ogg_d->num_sub); extra_size = get_uint16(pack.packet+140); sh_a->wf = (WAVEFORMATEX*)calloc(1,sizeof(WAVEFORMATEX)+extra_size); sh_a->format = sh_a->wf->wFormatTag = get_uint16(pack.packet+124); sh_a->channels = sh_a->wf->nChannels = get_uint16(pack.packet+126); sh_a->samplerate = sh_a->wf->nSamplesPerSec = get_uint32(pack.packet+128); sh_a->wf->nAvgBytesPerSec = get_uint32(pack.packet+132); sh_a->wf->nBlockAlign = get_uint16(pack.packet+136); sh_a->wf->wBitsPerSample = get_uint16(pack.packet+138); sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8; sh_a->wf->cbSize = extra_size; if(extra_size > 0) memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),pack.packet+142,extra_size); ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", n_audio); ogg_d->subs[ogg_d->num_sub].id = n_audio; n_audio++; mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d->num_sub,sh_a->format,n_audio-1); if(verbose>0) print_wave_header(sh_a->wf); } else mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg stream %d contains an old header but the header type is unknown\n",ogg_d->num_sub); // Check new header } else if ( (*pack.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER && pack.bytes >= (int)sizeof(stream_header)+1) { stream_header *st = (stream_header*)(pack.packet+1); /// New video header if(strncmp(st->streamtype,"video",5) == 0) { sh_v = new_sh_video(demuxer,ogg_d->num_sub); sh_v->bih = (BITMAPINFOHEADER*)calloc(1,sizeof(BITMAPINFOHEADER)); sh_v->bih->biSize=sizeof(BITMAPINFOHEADER); sh_v->bih->biCompression= sh_v->format = mmioFOURCC(st->subtype[0],st->subtype[1], st->subtype[2],st->subtype[3]); sh_v->frametime = get_uint64(&st->time_unit)*0.0000001; sh_v->fps = 1.0/sh_v->frametime; sh_v->bih->biBitCount = get_uint16(&st->bits_per_sample); sh_v->disp_w = sh_v->bih->biWidth = get_uint32(&st->sh.video.width); sh_v->disp_h = sh_v->bih->biHeight = get_uint32(&st->sh.video.height); if(!sh_v->bih->biBitCount) sh_v->bih->biBitCount=24; // hack, FIXME sh_v->bih->biPlanes=1; sh_v->bih->biSizeImage=(sh_v->bih->biBitCount>>3)*sh_v->bih->biWidth*sh_v->bih->biHeight; ogg_d->subs[ogg_d->num_sub].samplerate= sh_v->fps; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_VIDEO_ID=%d\n", n_video); ogg_d->subs[ogg_d->num_sub].id = n_video; n_video++; mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: video (FOURCC %c%c%c%c), -vid %d\n", ogg_d->num_sub,st->subtype[0],st->subtype[1],st->subtype[2],st->subtype[3],n_video-1); if(verbose>0) print_video_header(sh_v->bih); /// New audio header } else if(strncmp(st->streamtype,"audio",5) == 0) { char buffer[5]; unsigned int extra_size = get_uint32 (&st->size) - sizeof(stream_header); memcpy(buffer,st->subtype,4); buffer[4] = '\0'; sh_a = new_sh_audio(demuxer,ogg_d->num_sub); sh_a->wf = (WAVEFORMATEX*)calloc(1,sizeof(WAVEFORMATEX)+extra_size); sh_a->format = sh_a->wf->wFormatTag = strtol(buffer, NULL, 16); sh_a->channels = sh_a->wf->nChannels = get_uint16(&st->sh.audio.channels); sh_a->samplerate = sh_a->wf->nSamplesPerSec = get_uint64(&st->samples_per_unit); sh_a->wf->nAvgBytesPerSec = get_uint32(&st->sh.audio.avgbytespersec); sh_a->wf->nBlockAlign = get_uint16(&st->sh.audio.blockalign); sh_a->wf->wBitsPerSample = get_uint16(&st->bits_per_sample); sh_a->samplesize = (sh_a->wf->wBitsPerSample+7)/8; sh_a->wf->cbSize = extra_size; if(extra_size) memcpy(((char *)sh_a->wf)+sizeof(WAVEFORMATEX),st+1,extra_size); ogg_d->subs[ogg_d->num_sub].samplerate = sh_a->samplerate; // * sh_a->channels; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_AUDIO_ID=%d\n", n_audio); ogg_d->subs[ogg_d->num_sub].id = n_audio; n_audio++; mp_msg(MSGT_DEMUX,MSGL_INFO,"[Ogg] stream %d: audio (format 0x%04x), -aid %d\n",ogg_d->num_sub,sh_a->format,n_audio-1); if(verbose>0) print_wave_header(sh_a->wf); /// Check for text (subtitles) header } else if (strncmp(st->streamtype, "text", 4) == 0) { mp_msg(MSGT_DEMUX, MSGL_INFO, "[Ogg] stream %d: subtitles (SRT-like text subtitles), -sid %d\n", ogg_d->num_sub, ogg_d->n_text); ogg_d->subs[ogg_d->num_sub].samplerate= get_uint64(&st->time_unit)/10; ogg_d->subs[ogg_d->num_sub].text = 1; if (identify) mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", ogg_d->n_text); ogg_d->subs[ogg_d->num_sub].id = ogg_d->n_text; if (demuxer->sub->id == ogg_d->n_text) text_id = ogg_d->num_sub; ogg_d->n_text++; ogg_d->text_ids = (int *)realloc(ogg_d->text_ids, sizeof(int) * ogg_d->n_text); ogg_d->text_ids[ogg_d->n_text - 1] = ogg_d->num_sub; ogg_d->text_langs = (char **)realloc(ogg_d->text_langs, sizeof(char *) * ogg_d->n_text); ogg_d->text_langs[ogg_d->n_text - 1] = NULL; demux_ogg_init_sub(); //// Unknown header type } else mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d has a header marker but is of an unknown type\n",ogg_d->num_sub); /// Unknown (invalid ?) header } else mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg stream %d is of an unknown type\n",ogg_d->num_sub); if(sh_a || sh_v) { demux_stream_t* ds = NULL; if(sh_a) { // If the audio stream is not defined we took the first one if(demuxer->audio->id == -1) { demuxer->audio->id = n_audio - 1;// if(sh_a->wf) print_wave_header(sh_a->wf); } /// Is it the stream we want if(demuxer->audio->id == (n_audio - 1)) { demuxer->audio->sh = sh_a; sh_a->ds = demuxer->audio; ds = demuxer->audio; audio_id = ogg_d->num_sub; } } if(sh_v) { /// Also for video if(demuxer->video->id == -1) { demuxer->video->id = n_video - 1;// if(sh_v->bih) print_video_header(sh_v->bih); } if(demuxer->video->id == (n_video - 1)) { demuxer->video->sh = sh_v; sh_v->ds = demuxer->video; ds = demuxer->video; video_id = ogg_d->num_sub; } } /// Add the header packets if the stream isn't seekable if(ds && !s->end_pos) { /// Finish the page, otherwise packets will be lost do { demux_ogg_add_packet(ds,&ogg_d->subs[ogg_d->num_sub],ogg_d->num_sub,&pack); } while(ogg_stream_packetout(&ogg_d->subs[ogg_d->num_sub].stream,&pack) == 1); } } ogg_d->num_sub++; } if(!n_video && !n_audio) { goto err_out; } /// Finish to setup the demuxer demuxer->priv = ogg_d; if(!n_video || (video_id < 0)) demuxer->video->id = -2; else demuxer->video->id = video_id; if(!n_audio || (audio_id < 0)) demuxer->audio->id = -2; else demuxer->audio->id = audio_id; /* Disable the subs only if there are no text streams at all. Otherwise the stream to display might be chosen later when the comment packet is encountered and the user used -slang instead of -sid. */ if(!ogg_d->n_text) demuxer->sub->id = -2; else if (text_id >= 0) { demuxer->sub->id = text_id; mp_msg(MSGT_DEMUX, MSGL_V, "Ogg demuxer: Displaying subtitle stream id %d\n", text_id); } ogg_d->final_granulepos=0; if(!s->end_pos) demuxer->seekable = 0; else { demuxer->movi_start = s->start_pos; // Needed for XCD (Ogg written in MODE2) demuxer->movi_end = s->end_pos; demuxer->seekable = 1; demux_ogg_scan_stream(demuxer); } mp_msg(MSGT_DEMUX,MSGL_V,"Ogg demuxer : found %d audio stream%s, %d video stream%s and %d text stream%s\n",n_audio,n_audio>1?"s":"",n_video,n_video>1?"s":"",ogg_d->n_text,ogg_d->n_text>1?"s":""); return 1;err_out: demux_close_ogg(demuxer); return 0;}int demux_ogg_fill_buffer(demuxer_t *d) { ogg_demuxer_t* ogg_d; stream_t *s; demux_stream_t *ds; ogg_sync_state* sync; ogg_stream_state* os; ogg_page* page; ogg_packet pack; int np = 0, id=0; s = d->stream; ogg_d = d->priv; sync = &ogg_d->sync; page = &ogg_d->page; /// Find the stream we are working on if ( (id = demux_ogg_get_page_stream(ogg_d,&os)) < 0) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Ogg demuxer : can't get current stream\n"); return 0; } while(1) { np = 0; ds = NULL; /// Try to get some packet from the current page while( (np = ogg_stream_packetout(os,&pack)) != 1) { /// No packet we go the next page if(np == 0) { while(1) { int pa,len; char *buf; ogg_d->pos += ogg_d->last_size; /// Get the next page from the physical stream while( (pa = ogg_sync_pageseek(sync,page)) <= 0) { /// Error : we skip some bytes if(pa < 0) { mp_msg(MSGT_DEMUX,MSGL_WARN,"Ogg : Page out not synced, we skip some bytes\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -