#include "vod-file-source.h" #include "sys/system.h" #include #include #include VodFileSource::VodFileSource(std::shared_ptr reader, std::shared_ptr listener) :m_status(STOP), m_running(true), m_speed(128), m_clock(0), m_timestamp(0), m_reader(reader), m_listener(listener) { thread_create(&m_thread, Worker, this); } VodFileSource::~VodFileSource() { m_running = false; m_event.Signal(); thread_destroy(m_thread); } int VodFileSource::Worker(void* param) { VodFileSource* s = (VodFileSource*)param; return s->Worker(); } int VodFileSource::Worker() { int r = 0; struct avpacket_t* pkt = NULL; if (!m_reader) return -1; do { while ((m_status == STOP || m_status == PAUSE) && m_running) m_event.Wait(); while (m_status == PLAY && 0 == r && m_running) { if (!pkt) { AutoThreadLocker locker(m_locker); r = m_reader->Read(&pkt); if (r <= 0) break; // all done r = 0; // 1 -> 0 } uint64_t now = system_time(); uint64_t timestamp = pkt ? (0 == pkt->dts || -1 == pkt->dts ? pkt->pts : pkt->dts) : m_timestamp; if (0 == m_clock || now < m_clock || timestamp < m_timestamp) { m_clock = now; m_timestamp = timestamp; } int64_t diff = (int64_t)((timestamp - m_timestamp) - ((now - m_clock) * m_speed / 128)); if (diff <= 0 || m_event.TimeWait((int)(diff * 128 / m_speed))) { if (m_listener) r = m_listener->OnPacket(pkt); avpacket_release(pkt); pkt = NULL; // reset } } } while (0 == r && m_running); avpacket_release(pkt); return 0; } int VodFileSource::Play() { if (PLAY != m_status) { m_clock = 0; m_timestamp = 0; m_status = PLAY; m_event.Signal(); } return 0; } int VodFileSource::Pause() { m_status = PAUSE; m_event.Signal(); return 0; } int VodFileSource::Seek(uint64_t* pos, int strategy) { AutoThreadLocker locker(m_locker); return m_reader->Seek(pos, strategy); } int VodFileSource::GetSpeed() const { return m_speed; } int VodFileSource::SetSpeed(int speed) { m_speed = speed; return 0; } uint64_t VodFileSource::GetPosition() const { return m_reader->GetPosotion(); } uint64_t VodFileSource::GetDuration() const { return m_reader->GetDuration(); }