// Copyright 2019 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "mjpeg_video_source.hh" #include "utils.h" namespace easymedia { MJPEGVideoSource* MJPEGVideoSource::createNew(UsageEnvironment& env, FramedSource* source) { return new MJPEGVideoSource(env, source); } MJPEGVideoSource::MJPEGVideoSource(UsageEnvironment& env, FramedSource* source) : JPEGVideoSource(env), m_inputSource(source), m_width(0), m_height(0), m_qTable0Init(false), m_qTable1Init(false) { memset(&m_qTable, 0, sizeof(m_qTable)); } MJPEGVideoSource::~MJPEGVideoSource() { Medium::close(m_inputSource); } void MJPEGVideoSource::doGetNextFrame() { if (m_inputSource) { m_inputSource->getNextFrame(fTo, fMaxSize, afterGettingFrame, this, FramedSource::handleClosure, this); } } void MJPEGVideoSource::doStopGettingFrames() { FramedSource::doStopGettingFrames(); if (m_inputSource) { m_inputSource->stopGettingFrames(); } } void MJPEGVideoSource::afterGettingFrame(void* clientData, unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds) { MJPEGVideoSource* source = (MJPEGVideoSource*)clientData; source->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds); } void MJPEGVideoSource::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes, struct timeval presentationTime, unsigned durationInMicroseconds) { int headerSize = 0; bool headerOk = false; fFrameSize = 0; for (unsigned int i = 0; i < frameSize; ++i) { // SOF if ((i + 8) < frameSize && fTo[i] == 0xFF && fTo[i + 1] == 0xC0) { m_height = (fTo[i + 5] << 5) | (fTo[i + 6] >> 3); m_width = (fTo[i + 7] << 5) | (fTo[i + 8] >> 3); } // DQT if ((i + 5 + 64) < frameSize && fTo[i] == 0xFF && fTo[i + 1] == 0xDB) { if (fTo[i + 4] == 0) { memcpy(m_qTable, fTo + i + 5, 64); m_qTable0Init = true; } else if (fTo[i + 4] == 1) { memcpy(m_qTable + 64, fTo + i + 5, 64); m_qTable1Init = true; } } // End of header if ((i + 1) < frameSize && fTo[i] == 0x3F && fTo[i + 1] == 0x00) { headerOk = true; headerSize = i + 2; break; } } if (headerOk) { fFrameSize = frameSize - headerSize; memmove(fTo, fTo + headerSize, fFrameSize); } fNumTruncatedBytes = numTruncatedBytes; fPresentationTime = presentationTime; fDurationInMicroseconds = durationInMicroseconds; afterGetting(this); } u_int8_t const* MJPEGVideoSource::quantizationTables(u_int8_t& precision, u_int16_t& length) { length = 0; precision = 0; if (m_qTable0Init && m_qTable1Init) { precision = 8; length = sizeof(m_qTable); } return m_qTable; } unsigned char MJPEGVideoSource::type() { return 1; }; unsigned char MJPEGVideoSource::qFactor() { return 128; }; unsigned char MJPEGVideoSource::width() { return m_width; }; unsigned char MJPEGVideoSource::height() { return m_height; }; } // namespace easymedia