📄 mp4.cpp
字号:
{ return MP4_ERROR_NOT_ALLOWED; } RMuint64 time = m_videoTime * 1000 / m_tracktimescales[m_videoTrackIndex]; if (time >= position_in_ms) { DEBUGMSG (1, ("-------------------------\n")); DEBUGMSG (1, ("VIDEO SEEK (slow method):\n")); DEBUGMSG (1, ("m_video_chunk_index: %lu\n", m_video_chunk_index)); DEBUGMSG (1, ("m_video_samples_per_chunk: %lu\n", m_video_samples_per_chunk)); DEBUGMSG (1, ("m_video_sample_count: %lu\n", m_video_sample_count)); DEBUGMSG (1, ("m_video_stts_sample_delta_count: %lu\n", m_video_stts_sample_delta_count)); DEBUGMSG (1, ("m_video_ctts_sample_delta_count: %lu\n", m_video_ctts_sample_delta_count)); DEBUGMSG (1, ("m_video_ctts_sample_delta: %lu\n", m_video_ctts_sample_delta)); DEBUGMSG (1, ("m_videoTime: %lu\n", m_videoTime)); DEBUGMSG (1, ("stco: %lu, %lu\n", m_video_stco.tell (), m_video_stco.get32 (&error))); DEBUGMSG (1, ("stts: %lu, %lu\n", m_video_stts.tell (), m_video_stts.get32 (&error))); DEBUGMSG (1, ("ctts: %lu, %lu\n", m_video_ctts.tell (), m_video_ctts.get32 (&error))); DEBUGMSG (1, ("stsz: %lu, %lu\n", m_video_stsz.tell (), m_video_stsz.get32 (&error))); DEBUGMSG (1, ("stsc: %lu, %lu\n", m_video_stsc.tell (), m_video_stsc.get32 (&error))); *fileoffset = chunk_offset; return MP4_ERROR_NO_ERROR; } m_video_stco.advance32 (&error); first_entry = m_video_stsc.get32 (&error); if (m_video_chunk_index == first_entry) { m_video_stsc.advance32 (&error); m_video_samples_per_chunk = m_video_stsc.get32 (&error); m_video_stsc.advance32 (&error); m_video_stsc.get32 (&error); m_video_stsc.advance32 (&error); } m_video_chunk_index++; for (i=0; ((RMint32)i)<m_video_samples_per_chunk; i++) { if (m_video_sample_size == 0) { chunk_length = m_video_stsz.get32 (&error); ASSERT (error == 0); m_video_stsz.advance32 (&error); } m_video_sample_count++; if (m_video_stts_sample_delta_count == 0) { m_video_stts_sample_delta_count = m_video_stts.get32 (&error); ASSERT (error == 0); m_video_stts.advance32 (&error); m_video_stts_sample_delta = m_video_stts.get32 (&error); ASSERT (error == 0); m_video_stts.advance32 (&error); } m_video_stts_sample_delta_count--; m_videoTime += m_video_stts_sample_delta; DEBUGMSG (0, ("videoSeek: m_videoTime = %d\n", (int)m_videoTime)); if (m_video_ctts.IsInitialized ()) { if (m_video_ctts_sample_delta_count == 0) { m_video_ctts_sample_delta_count = m_video_ctts.get32 (&error); ASSERT (error == 0); m_video_ctts.advance32 (&error); m_video_ctts_sample_delta = m_video_ctts.get32 (&error); ASSERT (error == 0); m_video_ctts.advance32 (&error); } m_video_ctts_sample_delta_count--; } } percent1 = (RMuint32)(time * 50 / position_in_ms); if (percent1 != percent0) m_CallbackTable.info (MP4_MSG_SEEK_PERCENTAGE, (void *)percent1, m_CallbackTable.context); percent0 = percent1; } ASSERT (0); return MP4_ERROR_NO_ERROR;}MP4_ERROR MP4Demux::audioSeek (RMuint64 position_in_ms, RMuint32 *fileoffset, RMuint32 isByteOffset){ RMuint32 chunk_offset, chunk_length, first_entry; RMuint32 error; RMuint32 i, ai; RMuint32 audiooffset[MP4_MAX_AUDIOTRACKS]; m_samples_per_chunk = 0; m_total_chunk_size = 0; m_chunkFlags = 0;/////////////////////////// for (i=0; i<MP4_MAX_AUDIOTRACKS; i++) { m_audio_stco[i].reset (); m_audio_stts[i].reset (); m_audio_ctts[i].reset (); m_audio_stsz[i].reset (); m_audio_stsc[i].reset (); m_audio_chunk_index[i] = 1; m_audio_samples_per_chunk[i] = 1; m_audio_sample_count[i] = 0; m_audio_stts_sample_delta_count[i] = 0; m_audio_ctts_sample_delta_count[i] = 0; m_audio_ctts_sample_delta[i] = 0; m_audioTime[i] = 0; audiooffset[i] = 0; } RMuint32 first_chunk, samples_per_chunk, sample_description_index, next_first_chunk; if (isByteOffset == 0) goto audio_seek_slow_way; for (ai=0; ai<(RMuint32)m_naudioStreams; ai++) { // seek to the correct offset in the stco table RMuint32 istart, imiddle, iend; RMuint32 current_offset; istart = 0; iend = m_audio_stco[ai].entrycount (); imiddle = (istart + iend) / 2; while (1) { m_audio_stco[ai].seek (imiddle * 4); current_offset = m_audio_stco[ai].get32 (&error); if ((imiddle == istart) || (imiddle == iend) || (current_offset == position_in_ms)) { if (current_offset == position_in_ms) { m_audio_chunk_index[ai] = imiddle + 1; } else { m_audio_stco[ai].seek (istart * 4); current_offset = m_audio_stco[ai].get32 (&error); if (current_offset > position_in_ms) { m_audio_chunk_index[ai] = istart + 1; } else { m_audio_stco[ai].seek (iend * 4); m_audio_chunk_index[ai] = iend + 1; } } break; } if (position_in_ms > current_offset) istart = imiddle; else iend = imiddle; imiddle = (istart + iend) / 2; } // at this point: // m_audio_chunk_index[ai] = chunk index corresponding to the place we want to seek to // m_audio_stco[ai] = correct position of the stco table // seek to the correct offset in the stsc table // m_audio_chunk_index[ai] is used as the reference point // m_audio_sample_count[ai] must be filled out as well m_audio_stts_sample_delta_count[ai] = 0; m_audio_sample_count[ai] = 0; m_audioTime[ai] = 0; next_first_chunk = 1; ASSERT (m_audio_stsc[ai].IsInitialized ()); while (1) { first_chunk = m_audio_stsc[ai].get32 (&error); if (error) { first_chunk = next_first_chunk; next_first_chunk++; } else { RMuint32 tmp; m_audio_stsc[ai].advance32 (&error); ASSERT (error == 0); samples_per_chunk = m_audio_stsc[ai].get32 (&error); m_audio_stsc[ai].advance32 (&error); ASSERT (error == 0); sample_description_index = m_audio_stsc[ai].get32 (&error); m_audio_stsc[ai].advance32 (&error); ASSERT (error == 0); tmp = m_audio_stsc[ai].get32 (&error); if (error) { first_chunk = next_first_chunk; next_first_chunk++; } else { next_first_chunk = tmp; } } if (next_first_chunk > m_audio_chunk_index[ai]) { m_audio_samples_per_chunk[ai] = samples_per_chunk; ASSERT (m_audio_chunk_index[ai] >= first_chunk); m_audio_sample_count[ai] += samples_per_chunk * (m_audio_chunk_index[ai] - first_chunk); break; } ASSERT (next_first_chunk >= first_chunk); m_audio_sample_count[ai] += samples_per_chunk * (next_first_chunk - first_chunk); } // seek to the correct offset in the stts table // m_audio_sample_count[ai] is used as the reference point m_audioTime[ai] = 0; if (m_audio_stts[ai].IsInitialized ()) { RMuint32 i, j, framecnt, n; framecnt = 0; error = 0; for (i=0; i<m_audio_stts[ai].entrycount (); i++) { n = m_audio_stts_sample_delta_count[ai] = m_audio_stts[ai].get32 (&error); m_audio_stts[ai].advance32 (&error); ASSERT (error == 0); m_audio_stts_sample_delta[ai] = m_audio_stts[ai].get32 (&error); m_audio_stts[ai].advance32 (&error); ASSERT (error == 0); for (j=0; j<n; j++) { m_audio_stts_sample_delta_count[ai]--; framecnt++; m_audioTime[ai] += m_audio_stts_sample_delta[ai]; if (framecnt == m_audio_sample_count[ai]) { goto audio_stts_table_finished; } } } }audio_stts_table_finished: // seek to the correct offset in the stts table // m_audio_sample_count[ai] is used as the reference point if (m_audio_ctts[ai].IsInitialized ()) { RMuint32 i, j, framecnt, n; framecnt = 0; error = 0; for (i=0; i<m_audio_ctts[ai].entrycount (); i++) { n = m_audio_ctts_sample_delta_count[ai] = m_audio_ctts[ai].get32 (&error); m_audio_ctts[ai].advance32 (&error); ASSERT (error == 0); m_audio_ctts_sample_delta[ai] = m_audio_ctts[ai].get32 (&error); m_audio_ctts[ai].advance32 (&error); ASSERT (error == 0); for (j=0; j<n; j++) { m_audio_ctts_sample_delta_count[ai]--; framecnt++; if (framecnt == m_audio_sample_count[ai]) { goto audio_ctts_table_finished; } } } }audio_ctts_table_finished: // seek to the correct stsz table position ASSERT (m_audio_stsz[ai].IsInitialized ()); if (m_audio_sample_size[ai] == 0) m_audio_stsz[ai].seek (m_audio_sample_count[ai] * 4); m_audio_stco[ai].seek ((m_audio_chunk_index[ai] - 1) * 4); audiooffset[ai] = m_audio_stco[ai].get32 (&error); DEBUGMSG (1, ("-------------------------\n")); DEBUGMSG (1, ("AUDIO SEEK (fast method): (%d)\n", (int)ai)); DEBUGMSG (1, ("m_audio_chunk_index: %lu\n", m_audio_chunk_index[ai])); DEBUGMSG (1, ("m_audio_samples_per_chunk: %lu\n", m_audio_samples_per_chunk[ai])); DEBUGMSG (1, ("m_audio_sample_count: %lu\n", m_audio_sample_count[ai])); DEBUGMSG (1, ("m_audio_stts_sample_delta_count: %lu\n", m_audio_stts_sample_delta_count[ai])); DEBUGMSG (1, ("m_audio_ctts_sample_delta_count: %lu\n", m_audio_ctts_sample_delta_count[ai])); DEBUGMSG (1, ("m_audio_ctts_sample_delta: %lu\n", m_audio_ctts_sample_delta[ai])); DEBUGMSG (1, ("m_audioTime: %lu\n", m_audioTime[ai])); DEBUGMSG (1, ("stco: %lu, %lu\n", m_audio_stco[ai].tell (), m_audio_stco[ai].get32 (&error))); DEBUGMSG (1, ("stts: %lu, %lu\n", m_audio_stts[ai].tell (), m_audio_stts[ai].get32 (&error))); DEBUGMSG (1, ("ctts: %lu, %lu\n", m_audio_ctts[ai].tell (), m_audio_ctts[ai].get32 (&error))); DEBUGMSG (1, ("stsz: %lu, %lu\n", m_audio_stsz[ai].tell (), m_audio_stsz[ai].get32 (&error))); DEBUGMSG (1, ("stsc: %lu, %lu\n", m_audio_stsc[ai].tell (), m_audio_stsc[ai].get32 (&error))); DEBUGMSG (1, ("-------------------------\n")); } if (audiooffset[0] && audiooffset[1]) *fileoffset = MP4_MIN (audiooffset[0], audiooffset[1]); else if (audiooffset[0]) *fileoffset = audiooffset[0]; else if (audiooffset[1]) *fileoffset = audiooffset[1]; else { ASSERT (0); return MP4_ERROR_FILE_TOO_SHORT; } return MP4_ERROR_NO_ERROR; for (i=0; i<MP4_MAX_AUDIOTRACKS; i++) { m_audio_stco[i].reset (); m_audio_stts[i].reset (); m_audio_ctts[i].reset (); m_audio_stsz[i].reset (); m_audio_stsc[i].reset (); m_audio_chunk_index[i] = 1; m_audio_samples_per_chunk[i] = 1; m_audio_sample_count[i] = 0; m_audio_stts_sample_delta_count[i] = 0; m_audio_ctts_sample_delta_count[i] = 0; m_audio_ctts_sample_delta[i] = 0; m_audioTime[i] = 0; audiooffset[i] = 0; } // the code below is a brute force methos to do seek, // it is really slow, but good for debugging if you want to check the results of // the above codeaudio_seek_slow_way: RMuint32 percent0, percent1; percent0 = (RMuint32)-1; RMint32 percent_complete = 50; audiooffset[0] = audiooffset[1] = 0; for (ai=0; ai<(RMuint32)m_naudioStreams; ai++) { RMint32 searching; searching = 1; while (searching) { chunk_offset = m_audio_stco[ai].get32 (&error); if (error) { return MP4_ERROR_NOT_ALLOWED; } if (isByteOffset) { if (chunk_offset >= (RMuint32)position_in_ms) { audiooffset[ai] = chunk_offset; searching = 0; percent_complete += 25; DEBUGMSG (1, ("-------------------------\n")); DEBUGMSG (1, ("AUDIO SEEK (slow method, byte): (%d)\n", (int)ai)); DEBUGMSG (1, ("m_audio_chunk_index: %lu\n", m_audio_chunk_index[ai])); DEBUGMSG (1, ("m_audio_samples_per_chunk: %lu\n", m_audio_samples_per_chunk[ai])); DEBUGMSG (1, ("m_audio_sample_count: %lu\n", m_audio_sample_count[ai])); DEBUGMSG (1, ("m_audio_stts_sample_delta_count: %lu\n", m_audio_stts_sample_delta_count[ai])); DEBUGMSG (1, ("m_audio_ctts_sample_delta_count: %lu\n", m_audio_ctts_sample_delta_count[ai])); DEBUGMSG (1, ("m_audio_ctts_sample_delta: %lu\n", m_audio_ctts_sample_delta[ai])); DEBUGMSG (1, ("m_audioTime: %lu\n", m_audioTime[ai])); DEBUGMSG (1, ("stco: %lu, %lu\n", m_audio_stco[ai].tell (), m_audio_stco[ai].get32 (&error))); DEBUGMSG (1, ("stts: %lu, %lu\n", m_audio_stts[ai].tell (), m_audio_stts[ai].get32 (&error))); DEBUGMSG (1, ("ctts: %lu, %lu\n", m_audio_ctts[ai].tell (), m_audio_ctts[ai].get32 (&error))); DEBUGMSG (1, ("stsz: %lu, %lu\n", m_audio_stsz[ai].tell (), m_audio_stsz[ai].get32 (&error))); DEBUGMSG (1, ("stsc: %lu, %lu\n", m_audio_stsc[ai].tell (), m_audio_stsc[ai].get32 (&error))); DEBUGMSG (1, ("------------------------------\n", (int)ai)); continue; } percent1 = (RMuint32)((RMint64)chunk_offset * 25 / (RMint64)position_in_ms) + percent_complete; if (percent1 != percent0) m_CallbackTable.info (MP4_MSG_SEEK_PERCENTAGE, (void *)percent1, m_CallbackTable.context); percent0 = percent1; } else { RMuint64 time = m_audioTime[ai] * 1000 / m_tracktimescales[m_audioTrackIndex[m_currentAudioTrack]]; if (time >= position_in_ms) { audiooffset[ai] = chunk_offset; searching = 0; percent_complete += 25; DEBUGMSG (1, ("------------------------------\n")); DEBUGMSG (1, ("AUDIO SEEK (slow method, time): (%d)\n", (int)ai)); DEBUGMSG (1, ("m_audio_chunk_index: %lu\n", m_audio_chunk_index[ai])); DEBUGMSG (1, ("m_audio_samples_per_chunk: %lu\n", m_audio_samples_per_chunk[ai])); DEBUGMSG (1, ("m_audio_sample_count: %lu\n", m_audio_sample_count[ai])); DEBUGMSG (1, ("m_audio_stts_sample_delta_count: %lu\n", m_audio_stts_sample_delta_count[ai])); DEBUGMSG (1, ("m_audio_ctts_sample_delta_count: %lu\n", m_audio_ctts_sample_delta_count[ai])); DEBUGMSG (1, ("m_audio_ctts_sample_delta: %lu\n", m_audio_ctts_sample_delta[ai])); DEBUGMSG (1, ("m_audioTime: %lu\n", m_audioTime[ai])); DEBUGMSG (1, ("stco: %lu, %lu\n", m_audio_stco[ai].tell (), m_audio_stco[ai].get32 (&error))); DEBUGMSG (1, ("stts: %lu, %lu\n", m_audio_stts[ai].tell (), m_audio_stts[ai].get32 (&error))); DEBUGMSG (1, ("ctts: %lu, %lu\n", m_audio_ctts[ai].tell (), m_audio_ctts[ai].get32 (&error))); DEBUGMSG (1, ("stsz: %lu, %lu\n", m_audio_stsz[ai].tell (), m_audio_stsz[ai].get32 (&error))); DEBUGMSG (1, ("stsc: %lu, %lu\n", m_audio_stsc[ai].tell (), m_audio_stsc[ai].get32 (&error))); DEBUGMSG (1, ("------------------------------\n")); continue; } percent1 = (RMuint32)((RMint64)time * 25 / (RMint64)position_in_ms) + percent_complete; if (percent1 != percent0) m_CallbackTable.info (MP4_MSG_SEEK_PERCENTAGE, (void *)percent1, m_CallbackTable.context); percent0 = percent1; } m_audio_stco[ai].advance32 (&error); first_entry = m_audio_stsc[ai].get32 (&error); if (m_audio_chunk_index[ai] == first_entry) { m_audio_stsc[ai].advance32 (&error); m_audio_samples_per_chunk[ai] = m_audio_stsc[ai].get32 (&error); m_audio_stsc[ai].advance32 (&error); m_audio_stsc[ai].get32 (&error); m_audio_stsc[ai].advance32 (&error); } m_audio_chunk_index[ai]++; for (i=0; i<(RMuint32)m_audio_samples_per_chunk[ai]; i++) { if (m_audio_sample_size[ai] == 0) { chunk_length = m_audio_st
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -