void mov_reader_test(const char* mp4) { s_vfp = fopen("v.h264", "wb"); s_afp = fopen("a.aac", "wb"); void* mov = mov_reader_create(mp4); mov_reader_getinfo(mov, mov_video_info, mov_audio_info, NULL); while (mov_reader_read(mov, s_buffer, sizeof(s_buffer), onread, NULL) > 0) { } mov_reader_destroy(mov); fclose(s_vfp); fclose(s_afp); }
int MP4FileSource::Play() { bool sendframe = false; if (3 == m_status) return 0; SEND_PACKET: if (0 == m_frame.bytes) { int r = mov_reader_read(m_reader, m_frame.buffer, sizeof(m_frame.buffer), MP4OnRead, &m_frame); if (r == 0) { // 0-EOF m_status = 3; SendBye(); return r; } else if (r < 0) { // error return r; } } m_status = 1; uint64_t clock = system_clock(); for (int i = 0; i < m_count; i++) { struct media_t* m = &m_media[i]; if (m->track != m_frame.track) continue; if (0 == m_clock || m_clock > clock) m_clock = clock; if (-1 == m_dts) m_dts = m_frame.dts; if (int64_t(clock - m_clock) + m_dts >= m_frame.dts) { if (0 == strcmp("H264", m->name)) { // MPEG4 -> H.264 byte stream uint8_t* p = m_frame.buffer; size_t bytes = m_frame.bytes; while (bytes > 0) { // nalu size -> start code assert(bytes > 4); uint32_t n = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; p[0] = 0; p[1] = 0; p[2] = 0; p[3] = 1; bytes -= n + 4; p += n + 4; } //printf("[V] pts: %lld, dts: %lld, clock: %llu\n", m_frame.pts, m_frame.dts, clock); } else if (0 == strcmp("MP4A-LATM", m->name) || 0 == strcmp("MPEG4-GENERIC", m->name)) { // add ADTS header //printf("[A] pts: %lld, dts: %lld, clock: %llu\n", m_frame.pts, m_frame.dts, clock); } else { assert(0); } if (-1 == m->dts_first) m->dts_first = m_frame.pts; m->dts_last = m_frame.pts; uint32_t timestamp = m->timestamp + m->dts_last - m->dts_first; /* if (-1 == m->dts) m->dts = m_frame.dts; m->timestamp += m_frame.dts - m->dts; m->dts = m_frame.dts; */ rtp_payload_encode_input(m->packer, m_frame.buffer, m_frame.bytes, (uint32_t)(timestamp * (m->frequency / 1000) /*kHz*/)); SendRTCP(m, clock); m_frame.bytes = 0; // send flag sendframe = 1; goto SEND_PACKET; } break; } return sendframe ? 1 : 0; }