📄 mp4.cpp
字号:
m_subpi_stco[si].advance32 (&error); m_State = MP4_DEMUX_STATE_PARSE_CHUNK; first_entry = m_subpi_stsc[si].get32 (&error); if (first_entry == m_subpi_chunk_index[si]) { m_subpi_stsc[si].advance32 (&error); m_subpi_samples_per_chunk[si] = m_subpi_stsc[si].get32 (&error); m_subpi_stsc[si].advance32 (&error); m_subpi_stsc[si].get32 (&error); m_subpi_stsc[si].advance32 (&error); } m_subpi_chunk_index[si]++; m_currentID = 2 | (si << 8); m_samples_per_chunk = m_subpi_samples_per_chunk[si]; ASSERT (m_samples_per_chunk); DEBUGMSG (0, ("m_subpi_samples_per_chunk: %d\n", (RMint32)m_subpi_samples_per_chunk)); ASSERT (m_samples_per_chunk > 0); } else { // resync to next audio/video/subpi chunk RMuint32 next_offset, aoffset, soffset; ASSERT (voffset || aoffset0 || soffset0 || aoffset1 || soffset1); if (soffset0 && soffset1) soffset = MP4_MIN (soffset0, soffset1); else soffset = soffset0; if (aoffset0 && aoffset1) aoffset = MP4_MIN (aoffset0, aoffset1); else aoffset = aoffset0; if (voffset && aoffset && soffset) { next_offset = MP4_MIN (soffset, aoffset); next_offset = MP4_MIN (voffset, next_offset); } else if (voffset && aoffset) next_offset = MP4_MIN (voffset, aoffset); else if (voffset == 0) next_offset = aoffset; else next_offset = voffset; DEBUGMSG (1, ("*** resync to: %d\n", (RMint32)next_offset)); // need to seek? if ((next_offset >= m_currentOffset) && (next_offset < (m_currentOffset + m_DataLeft))) { ASSERT ((RMint32)(next_offset - m_currentOffset) > 0); ASSERT ((RMint32)(next_offset - m_currentOffset) < (RMint32)m_DataLeft); m_pPutData += (RMint32)(next_offset - m_currentOffset); m_DataLeft -= (RMint32)(next_offset - m_currentOffset); ASSERT ((RMint32)m_DataLeft > 0); m_currentOffset = next_offset; m_DataLength = m_DataLeft; ASSERT ((RMint32)m_DataLength > 0); } else { m_currentOffset = next_offset; ASSERT (m_currentOffset); m_CallbackTable.fseek (m_handle, next_offset, SEEK_SET, m_CallbackTable.context); ASSERT (m_pData); m_CallbackTable.release (m_pData, m_CallbackTable.context); m_pData = 0; m_State = MP4_DEMUX_STATE_GET_DATA; } } } break; case MP4_DEMUX_STATE_PARSE_CHUNK: if ((m_currentID & 0xff) == 0) { ASSERT (m_samples_per_chunk >= 0); DEBUGMSG (0, ("(v) m_samples_per_chunk: %d\n", m_samples_per_chunk)); m_samples_per_chunk--; if (m_samples_per_chunk < 0) { m_State = MP4_DEMUX_STATE_PARSE_DATA; break; } m_total_chunk_size = 0; m_chunkFlags = CHUNK_FLAGS_TIME_VALID; if (m_video_sample_size == 0) { m_total_chunk_size = m_video_stsz.get32 (&error); DEBUGMSG (0, (" video sample size: %d\n", (RMint32)m_total_chunk_size)); m_video_stsz.advance32 (&error); } else { m_total_chunk_size = m_video_sample_size; } m_firstVideoChunk = 0; 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); if (error == 0) { m_video_stts.advance32 (&error); m_video_stts_sample_delta = m_video_stts.get32 (&error); m_video_stts.advance32 (&error); } } m_video_stts_sample_delta_count--; if (m_video_ctts.IsInitialized ()) { DEBUGMSG (0, ("m_video_ctts_sample_delta_count = %d\n", (int)m_video_ctts_sample_delta_count)); if (m_video_ctts_sample_delta_count == 0) { m_video_ctts_sample_delta_count = m_video_ctts.get32 (&error); ASSERT (error == 0); if (error == 0) { m_video_ctts.advance32 (&error); m_video_ctts_sample_delta = m_video_ctts.get32 (&error); DEBUGMSG (0, ("m_video_ctts_sample_delta = %d\n", (int)m_video_ctts_sample_delta)); m_video_ctts.advance32 (&error); } } m_video_ctts_sample_delta_count--; m_chunkTime = m_videoTime + m_video_ctts_sample_delta; DEBUGMSG (0, ("m_chunkTime = %d (%d + %d)\n", (int)m_chunkTime, (int)m_videoTime, (int)m_video_ctts_sample_delta)); m_videoTime += m_video_stts_sample_delta; } else { m_chunkTime = m_videoTime; DEBUGMSG (0, ("m_chunkTime = %d (%d)\n", (int)m_chunkTime, (int)m_videoTime)); m_videoTime += m_video_stts_sample_delta; } m_chunkFlags |= CHUNK_FLAGS_SAMPLE_START; m_State = MP4_DEMUX_STATE_SEND_DATA; } else if ((m_currentID & 0xff) == 1) { RMint32 ai; ai = m_current_au_index; ASSERT (m_samples_per_chunk >= 0); DEBUGMSG (0, ("(a) m_samples_per_chunk: %d\n", m_samples_per_chunk)); m_samples_per_chunk--; if (m_samples_per_chunk < 0) { m_State = MP4_DEMUX_STATE_PARSE_DATA; break; } m_total_chunk_size = 0; m_chunkFlags = CHUNK_FLAGS_TIME_VALID; if (m_audio_sample_size[ai] == 0) { m_total_chunk_size = m_audio_stsz[ai].get32 (&error); ASSERT (m_total_chunk_size <= 4096); ASSERT (m_total_chunk_size); ASSERT (error == 0); m_audio_stsz[ai].advance32 (&error); ASSERT (error == 0); } else { m_total_chunk_size = m_audio_sample_size[ai]; ASSERT (m_total_chunk_size); } ASSERT (m_total_chunk_size <= 4096); DEBUGMSG ((m_total_chunk_size > 4096), ("audio error: m_audio_sample_size = %d, m_total_chunk_size = %08lx\n", m_audio_sample_size, m_total_chunk_size)); m_audio_sample_count[ai]++; if (m_audio_stts_sample_delta_count[ai] == 0) { m_audio_stts_sample_delta_count[ai] = m_audio_stts[ai].get32 (&error); ASSERT (error == 0); if (error == 0) { m_audio_stts[ai].advance32 (&error); m_audio_stts_sample_delta[ai] = m_audio_stts[ai].get32 (&error); m_audio_stts[ai].advance32 (&error); } } m_audio_stts_sample_delta_count[ai]--; m_chunkTime = m_audioTime[ai]; m_audioTime[ai] += m_audio_stts_sample_delta[ai]; m_chunkFlags |= CHUNK_FLAGS_SAMPLE_START; m_State = MP4_DEMUX_STATE_SEND_DATA; } else if ((m_currentID & 0xff) == 2) { RMint32 si; si = m_current_sp_index; ASSERT (m_samples_per_chunk >= 0); DEBUGMSG (0, ("(s) m_samples_per_chunk: %d\n", m_samples_per_chunk)); m_samples_per_chunk--; if (m_samples_per_chunk < 0) { m_State = MP4_DEMUX_STATE_PARSE_DATA; break; } m_total_chunk_size = 0; m_chunkFlags = CHUNK_FLAGS_TIME_VALID; if (m_subpi_sample_size[si] == 0) { m_total_chunk_size = m_subpi_stsz[si].get32 (&error); ASSERT (m_total_chunk_size); m_subpi_stsz[si].advance32 (&error); } else { m_total_chunk_size = m_subpi_sample_size[si]; ASSERT (m_total_chunk_size); } m_subpi_sample_count[si]++; if (m_subpi_stts_sample_delta_count[si] == 0) { m_subpi_stts_sample_delta_count[si] = m_subpi_stts[si].get32 (&error); ASSERT (error == 0); if (error == 0) { m_subpi_stts[si].advance32 (&error); m_subpi_stts_sample_delta[si] = m_subpi_stts[si].get32 (&error); m_subpi_stts[si].advance32 (&error); } } m_subpi_stts_sample_delta_count[si]--; m_chunkTime = m_subpiTime[si]; m_subpiTime[si] += m_subpi_stts_sample_delta[si]; m_chunkFlags |= CHUNK_FLAGS_SAMPLE_START; m_State = MP4_DEMUX_STATE_SEND_DATA; } else ASSERT (0); break; case MP4_DEMUX_STATE_SEND_DATA: { RMuint32 l; // write m_total_chunk_size data l = MP4_MIN (m_total_chunk_size, m_DataLeft); if (l == m_total_chunk_size) m_chunkFlags |= CHUNK_FLAGS_SAMPLE_END; if (m_CallbackTable.putChunk (m_currentID, m_chunkFlags, m_chunkTime, m_pPutData, l, m_CallbackTable.context) != 0) { ASSERT (0); break; } m_chunkFlags &= ~(CHUNK_FLAGS_TIME_VALID | CHUNK_FLAGS_SAMPLE_START | CHUNK_FLAGS_SAMPLE_END); m_total_chunk_size -= l; m_currentOffset += l; ASSERT (m_currentOffset); m_pPutData += l; m_DataLeft -= l; ASSERT ((RMint32)m_DataLeft >= 0); if (m_DataLeft == 0) { ASSERT (m_pData); m_CallbackTable.release (m_pData, m_CallbackTable.context); m_pData = 0; m_State = MP4_DEMUX_STATE_GET_DATA; } else { ASSERT (m_total_chunk_size == 0); m_State = MP4_DEMUX_STATE_PARSE_CHUNK; } } break; case MP4_RANDOM_ACCESS_ONLY: RandomAccessPointsOnly (); break; case MP4_DEMUX_STATE_END_OF_FILE: return MP4_ERROR_END_OF_FILE; break; default: break; } return MP4_ERROR_NO_ERROR;}#define PROCESS_CURRENT_RANDOM_ACCESS_POINT 0#define GET_RANDOM_ACCESS_DATA 1#define READ_CURRENT_RANDOM_ACCESS_POINT 2#define UPDATE_NEXT_RANDOM_ACCESS_POINT 3#define UPDATE_PREVIOUS_RANDOM_ACCESS_POINT 4RMuint32 MP4Demux::RandomAccessPointsOnly (){ RMuint32 error, sample_size, chunk_sample_count; RMuint32 first_chunk, next_chunk, sample_description_index, chunk_offset, frame_no, chunk_index; RMint32 sample_offset, i, frame_incr, rewind; switch (m_RandomAccessState) { case PROCESS_CURRENT_RANDOM_ACCESS_POINT: // before coming here, these variables should be initalized: // m_currentRandomAccessPoint // m_video_chunk_index // m_video_samples_per_chunk // m_samples_per_chunk // m_video_sample_count // find the chunk that this sample is in chunk_index = m_video_chunk_index - 1; chunk_index += (m_currentRandomAccessPoint - m_video_sample_count) / m_samples_per_chunk; chunk_sample_count = m_video_sample_count + ((m_currentRandomAccessPoint - m_video_sample_count)/m_samples_per_chunk)*m_samples_per_chunk; m_video_stco.seek (chunk_index * 4); chunk_offset = m_video_stco.get32 (&error); ASSERT (error == 0); // find the offset to this sample within this chunk sample_offset = m_currentRandomAccessPoint - chunk_sample_count; // calculate the file position of this random access point if (m_video_sample_size) { chunk_offset += (m_video_sample_size * sample_offset); sample_size = m_video_sample_size; } else { m_video_stsz.seek (chunk_sample_count * 4); for (i=0; i<sample_offset; i++) { chunk_offset += m_video_stsz.get32 (&error); m_video_stsz.advance32 (&error); ASSERT (error == 0); } // calculate the size of this random access point sample_size = m_video_stsz.get32 (&error); ASSERT (error == 0); m_video_stsz.seek (m_currentRandomAccessPoint * 4); sample_size = m_video_stsz.get32 (&error); ASSERT (error == 0); } seek (chunk_offset); m_RandomAccessSampleSize = sample_size; ASSERT (m_RandomAccessSampleSize); m_RandomAccessState = GET_RANDOM_ACCESS_DATA; m_chunkFlags = CHUNK_FLAGS_TIME_VALID | CHUNK_FLAGS_SAMPLE_START; m_chunkTime = m_currentRandomAccessPoint * m_video_stts_sample_delta;#ifdef MP4_ENABLE_DEBUG { static int IFrameCounter = 0; RMint32 h, m, s, t; t = (RMint32)(m_chunkTime / m_tracktimescales[m_videoTrackIndex]); h = (t / 3600); m = (t - h * 3600) / 60; s = t - h*3600 - m*60; DEBUGMSG (1, ("(%d) send frame %d @%d %d bytes (%02d:%02d:%02d)\n", IFrameCounter++, (int)m_currentRandomAccessPoint, (int)chunk_offset, (int)sample_size, h, m, s)); } if (f == 0) f = fopen ("d:\\iframe.m4v", "wb"); #endif break; case GET_RANDOM_ACCESS_DATA: ASSERT (m_pRandomAccessData == 0); if (m_CallbackTable.getData (&m_pRandomAccessData, &m_RandomLength, m_CallbackTable.context) == 0) { ASSERT (m_RandomLength); m_CallbackTable.addref (m_pRandomAccessData, m_CallbackTable.context); m_RandomAccessState = READ_CURRENT_RANDOM_ACCESS_POINT; } break; case READ_CURRENT_RANDOM_ACCESS_POINT: sample_size = MP4_MIN (m_RandomLength, m_RandomAccessSampleSize); sample_size = m_CallbackTable.fread (m_handle, m_pRandomAccessData, sample_size, m_CallbackTable.context);#ifdef MP4_ENABLE_DEBUG if (f) { fwrite (m_pRandomAccessData, 1, sample_size, f); } #endif if (sample_size == 0) { ASSERT (0); m_State = MP4_DEMUX_STATE_END_OF_FILE; return MP4_ERROR_NO_ERROR; } ASSERT (m_pRandomAccessData); DEBUGMSG (0, (" putChunk (%08lx, %08lx%08lx, %08lx, %d)\n", (RMuint32)(m_chunkFlags), (RMuint32)(m_chunkTime >> 32), (RMuint32)(m_chunkTime), (RMuint32)m_pRandomAccessData, (int)sample_size)); if (m_CallbackTable.putChunk (0, m_chunkFlags, m_chunkTime, m_pRandomAccessData, sample_size, m_CallbackTable.context) != 0) { ASSERT (0); m_State = MP4_DEMUX_STATE_END_OF_FILE; return MP4_ERROR_NO_ERROR; } m_CallbackTable.release (m_pRandomAccessData, m_CallbackTable.context); m_chunkTime = 0; m_chunkFlags = 0; m_pRandomAccessData = 0; m_RandomAccessSampleSize -= sample_size; if (m_RandomAccessSampleSize == 0) { if (m_RandomAccessPointsOnly > 0) m_RandomAccessState = UPDATE_NEXT_RANDOM_ACCESS_POINT; else m_RandomAccessState = UPDATE_PREVIOUS_RANDOM_ACCESS_POINT; } else m_RandomAccessState = GET_RANDOM_ACCESS_DATA; break; case UPDATE_NEXT_RANDOM_ACCESS_POINT: // re-initialize: // m_currentRandomAccessPoint // m_video_chunk_index // m_video_samples_per_chunk // m_samples_per_chunk // m_video_sample_count ASSERT (m_RandomAccessPointsOnly > 0); m_currentRandomAccessPoint = m_video_stss.get32 (&error) - 1; m_video_stss.advance32 (&error);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -