📄 demux_real.c
字号:
break; case 0x10003000: case 0x10003001: /* sub id: 3 */ /* codec id: rv10 */ sh->bih->biCompression = sh->format = mmioFOURCC('R', 'V', '1', '3'); break; case 0x20001000: case 0x20100001: case 0x20200002: /* codec id: rv20 */ break; case 0x30202002: /* codec id: rv30 */ break; case 0x40000000: /* codec id: rv40 */ break; default: /* codec id: none */ mp_msg(MSGT_DEMUX,MSGL_V,"unknown id: %x\n", tmp); } if((sh->format<=0x30335652) && (tmp>=0x20200002)){ // read data for the cmsg24[] (see vd_realvid.c) unsigned int cnt = codec_data_size - (stream_tell(demuxer->stream) - codec_pos); if (cnt < 2) { mp_msg(MSGT_DEMUX, MSGL_ERR,"realvid: cmsg24 data too short (size %u)\n", cnt); } else { int ii; if (cnt > 6) { mp_msg(MSGT_DEMUX, MSGL_WARN,"realvid: cmsg24 data too big, please report (size %u)\n", cnt); cnt = 6; } for (ii = 0; ii < cnt; ii++) ((unsigned char*)(sh->bih+1))[8+ii]=(unsigned short)stream_read_char(demuxer->stream); } } /* Select video stream with highest bitrate if multirate file*/ if (priv->is_multirate && ((demuxer->video->id == -1) || ((demuxer->video->id >= 0) && priv->v_bitrate && (bitrate > priv->v_bitrate)))) { demuxer->video->id = stream_id; priv->v_bitrate = bitrate; mp_msg(MSGT_DEMUX,MSGL_DBG2,"Multirate autoselected video id %d with bitrate %d\n", stream_id, bitrate); } if(demuxer->video->id==stream_id){ demuxer->video->id=stream_id; sh->ds=demuxer->video; demuxer->video->sh=sh; } ++v_streams; } } else { mp_msg(MSGT_DEMUX,MSGL_V,"Unknown video stream format\n"); } } else if (strstr(mimet,"logical-")) { if (strstr(mimet,"fileinfo")) { mp_msg(MSGT_DEMUX,MSGL_V,"Got a logical-fileinfo chunk\n"); } else if (strstr(mimet,"-audio") || strstr(mimet,"-video")) { int i, stream_cnt; int stream_list[MAX_STREAMS]; priv->is_multirate = 1; stream_skip(demuxer->stream, 4); // Length of codec data (repeated) stream_cnt = stream_read_dword(demuxer->stream); // Get number of audio or video streams if (stream_cnt >= MAX_STREAMS) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Too many streams in %s. Big troubles ahead.\n", mimet); goto skip_this_chunk; } for (i = 0; i < stream_cnt; i++) stream_list[i] = stream_read_word(demuxer->stream); for (i = 0; i < stream_cnt; i++) if (stream_list[i] >= MAX_STREAMS) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Stream id out of range: %d. Ignored.\n", stream_list[i]); stream_skip(demuxer->stream, 4); // Skip DATA offset for broken stream } else { priv->str_data_offset[stream_list[i]] = stream_read_dword(demuxer->stream); mp_msg(MSGT_DEMUX,MSGL_V,"Stream %d with DATA offset 0x%08x\n", stream_list[i], priv->str_data_offset[stream_list[i]]); } // Skip the rest of this chunk } else mp_msg(MSGT_DEMUX,MSGL_V,"Unknown logical stream\n"); } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "Not audio/video stream or unsupported!\n"); }// break;// default:skip_this_chunk: /* skip codec info */ tmp = stream_tell(demuxer->stream) - codec_pos; mp_msg(MSGT_DEMUX,MSGL_V,"### skipping %d bytes of codec info\n", codec_data_size - tmp);#if 0 { int i; for(i=0;i<codec_data_size - tmp;i++) mp_msg(MSGT_DEMUX, MSGL_V," %02X",stream_read_char(demuxer->stream)); mp_msg(MSGT_DEMUX, MSGL_V,"\n"); }#else stream_skip(demuxer->stream, codec_data_size - tmp);#endif if (mimet) free (mimet); break;// } } case MKTAG('D', 'A', 'T', 'A'): goto header_end; case MKTAG('I', 'N', 'D', 'X'): default: mp_msg(MSGT_DEMUX,MSGL_V,"Unknown chunk: %x\n", chunk_id); stream_skip(demuxer->stream, chunk_size - 10); break; } }header_end: if(priv->is_multirate) { mp_msg(MSGT_DEMUX,MSGL_V,"Selected video id %d audio id %d\n", demuxer->video->id, demuxer->audio->id); /* Perform some sanity checks to avoid checking streams id all over the code*/ if (demuxer->audio->id >= MAX_STREAMS) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Invalid audio stream %d. No sound will be played.\n", demuxer->audio->id); demuxer->audio->id = -2; } else if ((demuxer->audio->id >= 0) && (priv->str_data_offset[demuxer->audio->id] == 0)) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Audio stream %d not found. No sound will be played.\n", demuxer->audio->id); demuxer->audio->id = -2; } if (demuxer->video->id >= MAX_STREAMS) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Invalid video stream %d. No video will be played.\n", demuxer->video->id); demuxer->video->id = -2; } else if ((demuxer->video->id >= 0) && (priv->str_data_offset[demuxer->video->id] == 0)) { mp_msg(MSGT_DEMUX,MSGL_ERR,"Video stream %d not found. No video will be played.\n", demuxer->video->id); demuxer->video->id = -2; } } if(priv->is_multirate && ((demuxer->video->id >= 0) || (demuxer->audio->id >=0))) { /* If audio or video only, seek to right place and behave like standard file */ if (demuxer->video->id < 0) { // Stream is audio only, or -novideo stream_seek(demuxer->stream, priv->data_chunk_offset = priv->str_data_offset[demuxer->audio->id]+10); priv->is_multirate = 0; } if (demuxer->audio->id < 0) { // Stream is video only, or -nosound stream_seek(demuxer->stream, priv->data_chunk_offset = priv->str_data_offset[demuxer->video->id]+10); priv->is_multirate = 0; } } if(!priv->is_multirate) {// printf("i=%d num_of_headers=%d \n",i,num_of_headers); priv->num_of_packets = stream_read_dword(demuxer->stream);// stream_skip(demuxer->stream, 4); /* number of packets */ stream_skip(demuxer->stream, 4); /* next data header */ mp_msg(MSGT_DEMUX,MSGL_V,"Packets in file: %d\n", priv->num_of_packets); if (priv->num_of_packets == 0) priv->num_of_packets = -10; } else { priv->audio_curpos = priv->str_data_offset[demuxer->audio->id] + 18; stream_seek(demuxer->stream, priv->str_data_offset[demuxer->audio->id]+10); priv->a_num_of_packets=priv->a_num_of_packets = stream_read_dword(demuxer->stream); priv->video_curpos = priv->str_data_offset[demuxer->video->id] + 18; stream_seek(demuxer->stream, priv->str_data_offset[demuxer->video->id]+10); priv->v_num_of_packets = stream_read_dword(demuxer->stream); priv->stream_switch = 1; /* Index required for multirate playback, force building if it's not there */ /* but respect user request to force index regeneration */ if (index_mode == -1) index_mode = 1; } priv->audio_need_keyframe = 0; priv->video_after_seek = 0; switch (index_mode){ case -1: // untouched if (priv->index_chunk_offset && (priv->index_chunk_offset < demuxer->movi_end)) { parse_index_chunk(demuxer); demuxer->seekable = 1; } break; case 1: // use (generate index) if (priv->index_chunk_offset && (priv->index_chunk_offset < demuxer->movi_end)) { parse_index_chunk(demuxer); demuxer->seekable = 1; } else { generate_index(demuxer); demuxer->seekable = 1; } break; case 2: // force generating index generate_index(demuxer); demuxer->seekable = 1; break; default: // do nothing break; } if(priv->is_multirate) demuxer->seekable = 0; // No seeking yet for multirate streams // detect streams: if(demuxer->video->id==-1 && v_streams>0){ // find the valid video stream: if(!ds_fill_buffer(demuxer->video)){ mp_msg(MSGT_DEMUXER,MSGL_INFO,"RM: " MSGTR_MissingVideoStream); } } if(demuxer->audio->id==-1 && a_streams>0){ // find the valid audio stream: if(!ds_fill_buffer(demuxer->audio)){ mp_msg(MSGT_DEMUXER,MSGL_INFO,"RM: " MSGTR_MissingAudioStream); } } if(demuxer->video->sh){ sh_video_t *sh=demuxer->video->sh; mp_msg(MSGT_DEMUX,MSGL_V,"VIDEO: %.4s [%08X,%08X] %dx%d (aspect %4.2f) %4.2f fps\n", &sh->format,((unsigned int*)(sh->bih+1))[1],((unsigned int*)(sh->bih+1))[0], sh->disp_w,sh->disp_h,sh->aspect,sh->fps); }}void demux_close_real(demuxer_t *demuxer){ int i; real_priv_t* priv = demuxer->priv; if (priv){ for(i=0; i<MAX_STREAMS; i++) if(priv->index_table[i]) free(priv->index_table[i]); free(priv); } return;}extern void resync_audio_stream(sh_audio_t * sh_audio);/* please upload RV10 samples WITH INDEX CHUNK */int demux_seek_real(demuxer_t *demuxer, float rel_seek_secs, int flags){ real_priv_t *priv = demuxer->priv; demux_stream_t *d_audio = demuxer->audio; demux_stream_t *d_video = demuxer->video; sh_audio_t *sh_audio = d_audio->sh; sh_video_t *sh_video = d_video->sh; int vid = d_video->id, aid = d_audio->id; int next_offset = 0; int cur_timestamp = 0; int streams = 0; int retried = 0; if (sh_video && (unsigned)vid < MAX_STREAMS && priv->index_table_size[vid]) streams |= 1; if (sh_audio && (unsigned)aid < MAX_STREAMS && priv->index_table_size[aid]) streams |= 2;// printf("streams: %d\n", streams); if (!streams) return 0; if (flags & 1) /* seek absolute */ priv->current_apacket = priv->current_vpacket = 0; if ((streams & 1) && priv->current_vpacket >= priv->index_table_size[vid]) priv->current_vpacket = priv->index_table_size[vid] - 1; if ((streams & 2) && priv->current_apacket >= priv->index_table_size[aid]) priv->current_apacket = priv->index_table_size[aid] - 1;// if (index_mode == 1 || index_mode == 2) { if (streams & 1) {// use the video index if we have one cur_timestamp = priv->index_table[vid][priv->current_vpacket].timestamp; if (rel_seek_secs > 0) while ((priv->index_table[vid][priv->current_vpacket].timestamp - cur_timestamp) < rel_seek_secs * 1000){ priv->current_vpacket += 1; if (priv->current_vpacket >= priv->index_table_size[vid]) { priv->current_vpacket = priv->index_table_size[vid] - 1; if (!retried) { stream_seek(demuxer->stream, priv->index_table[vid][priv->current_vpacket].offset); add_index_segment(demuxer, vid, cur_timestamp + rel_seek_secs * 1000); retried = 1; } else break; } } else if (rel_seek_secs < 0) while ((cur_timestamp - priv->index_table[vid][priv->current_vpacket].timestamp) < - rel_seek_secs * 1000){ priv->current_vpacket -= 1; if (priv->current_vpacket < 0) { priv->current_vpacket = 0; break; } } next_offset = priv->index_table[vid][priv->current_vpacket].offset; priv->audio_need_keyframe = 1; priv->video_after_seek = 1; } else if (streams & 2) { cur_timestamp = priv->index_table[aid][priv->current_apacket].timestamp; if (rel_seek_secs > 0) while ((priv->index_table[aid][priv->current_apacket].timestamp - cur_timestamp) < rel_seek_secs * 1000){ priv->current_apacket += 1; if (priv->current_apacket >= priv->index_table_size[aid]) { priv->current_apacket = priv->index_table_size[aid] - 1; break; } } else if (rel_seek_secs < 0) while ((cur_timestamp - priv->index_table[aid][priv->current_apacket].timestamp) < - rel_seek_secs * 1000){ priv->current_apacket -= 1; if (priv->current_apacket < 0) { priv->current_apacket = 0; break; } } next_offset = priv->index_table[aid][priv->current_apacket].offset; }// }// printf("seek: pos: %d, current packets: a: %d, v: %d\n",// next_offset, priv->current_apacket, priv->current_vpacket); if (next_offset) stream_seek(demuxer->stream, next_offset); demux_real_fill_buffer(demuxer); if (sh_audio) resync_audio_stream(sh_audio); return 1;}int demux_real_control(demuxer_t *demuxer, int cmd, void *arg){ real_priv_t *priv = demuxer->priv; int lastpts = priv->v_pts ? priv->v_pts : priv->a_pts; switch (cmd) { case DEMUXER_CTRL_GET_TIME_LENGTH: if (priv->duration == 0) return DEMUXER_CTRL_DONTKNOW; *((unsigned long *)arg) = priv->duration; return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_PERCENT_POS: if (priv->duration == 0) return DEMUXER_CTRL_DONTKNOW; *((int *)arg) = (int)(100 * lastpts / priv->duration); return DEMUXER_CTRL_OK; default: return DEMUXER_CTRL_NOTIMPL; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -