/*************************************************************************** * stillimage.c * (C) Copyright 2004 * Created: Thu Aug 5 2004 * * parts of the code (c) Peter Seyringer * (c) Marcel Wiesweg ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Library General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include "stillimage.h" #include "stillimage-player.h" cStillImage::cStillImage(cStillImagePlayer *pl) { m_bThreadRun=false; m_bEncodeRequired = false; player=pl; } cStillImage::~cStillImage() { } bool cStillImage::Init() { return Start(); } void cStillImage::Stop() { if (!m_bThreadRun) return; m_bThreadRun=false; Cancel(3); } void cStillImage::Action(void) { m_bThreadRun=true; bool bMPEGValid = false; bool bQueueEmpty = false; bool bFreeze = true; unsigned int nFrame = 0,nFrameOff=0; int nMircoSekWait; while (m_bThreadRun) { nMircoSekWait = 10000; bQueueEmpty = player->Worker(false); if(!bQueueEmpty) { if(!bFreeze) { player->DeviceFreeze(); bFreeze = true; } player->Worker(true); } if(m_bEncodeRequired && bQueueEmpty) { //convert data to MPEG Lock(); bMPEGValid = Encode(); Unlock(); if (!m_bThreadRun) break; m_bEncodeRequired = false; nFrame = 0; nFrameOff=0; if(bFreeze) { player->DevicePlay(); bFreeze = false; } } if(bMPEGValid && bQueueEmpty) { /* Methode A ************************************************************/ /*timeval timenow,diff,timestart; gettimeofday(×tart, 0); for (int i=1;i<=25 && player->active;i++) { gettimeofday(&timenow, 0); timersub(&timenow, ×tart, &diff); BuildPesPacket(Data(), Size(),(int)(diff.tv_sec*90000.0 + (diff.tv_usec*90000.0)/1000000.0)); player->Wait(); }*/ /* Methode B ************************************************************/ //for (int i=1;i<= 25 && player->m_bActive;i++) { // BuildPesPacket(Data(), Size(),i); //} /* Methode C ************************************************************/ //BuildPesPacket(Data(), Size(),1); /* Methode D ************************************************************/ //player->DeviceStillPicture(Data(), Size()); /* Methode E ************************************************************/ unsigned int nFrameSize = GetFrameSize(nFrame); if(nFrameSize) // Skip empty Frames { BuildPesPacket(Data() + nFrameOff, nFrameSize,1); nFrameOff += nFrameSize; } if(++nFrame>=GetFrames()) { nFrame = 0; nFrameOff = 0; } nMircoSekWait = (1000000/(GetFrameRate()*4)); // Wait duration off 1/4 frame if (!m_bThreadRun) break; } //Reduce CPU load!!! usleep(max(10000,nMircoSekWait)); } m_bThreadRun=false; } //taken from mp1osd.c void cStillImage::BuildPesPacket(const unsigned char *data, int len, int timestamp) { #define PES_MAX_SIZE 2048 int ptslen = timestamp ? 5 : 1; static unsigned char pes_header[PES_MAX_SIZE]; // startcode: pes_header[0] = pes_header[1] = 0; pes_header[2] = 1; pes_header[3] = 0xe0; while (len > 0) { int payload_size = len; // data + PTS if (6 + ptslen + payload_size > PES_MAX_SIZE) payload_size = PES_MAX_SIZE - (6 + ptslen); // construct PES header: (code from ffmpeg's libav) // packetsize: pes_header[4] = (ptslen + payload_size) >> 8; pes_header[5] = (ptslen + payload_size) & 255; if (ptslen == 5) { int x; // presentation time stamp: x = (0x02 << 4) | (((timestamp >> 30) & 0x07) << 1) | 1; pes_header[8] = x; x = ((((timestamp >> 15) & 0x7fff) << 1) | 1); pes_header[7] = x >> 8; pes_header[8] = x & 255; x = ((((timestamp) & 0x7fff) << 1) | 1); pes_header[9] = x >> 8; pes_header[10] = x & 255; } else { // stuffing and header bits: pes_header[6] = 0x0f; } memcpy (&pes_header[6 + ptslen], data, payload_size); player->Wait(); player->Play(pes_header, 6 + ptslen + payload_size); len -= payload_size; data += payload_size; ptslen = 1; // store PTS only once, at first packet! } }