Hi, I have been trying to use Live555 to stream a JPEG file to OpenRTSP and other Live555 based clients.
Depending on the source JPEG file I get varying results in quality. When streaming the JPEG file I am simply finding the SOS marker and copying this to fTo, the code is below. I am starting to think that I need to be something else here as at the client side, for example OpenRTSP, isn't the exact same image. For example, if I connect to an IP camera, streaming MJPEG, with OpenRTSP I can get an image saved as a JPEG using: ./openRTSP -m rtsp://.... I then use this same image with the code below and use openRTSP again to stream the image and I get something far blockier. Where am I going wrong? Thanks in advance Andy TestJPEGVideoSource* TestJPEGVideoSource::createNew(UsageEnvironment& env, const char * fileName, unsigned int timePerFrame) { FILE * fid = fopen( fileName, "r" ); if ( fid == NULL ) { env.setResultErrMsg( "Failed to open input device file" ); return NULL; } return new TestJPEGVideoSource( env, fid, timePerFrame ); } TestJPEGVideoSource::TestJPEGVideoSource(UsageEnvironment& env, FILE* fid, unsigned int timePerFrame) : JPEGVideoSource(env), fFid(fid), fTimePerFrame(timePerFrame), fNeedAFrame(False) { this->buffer = NULL; fseek( fid, 0L, SEEK_END ); size_t sz = ftell( fFid ); fseek( fid, 0L, SEEK_SET ); buffer = new unsigned char[ sz ]; fread( buffer, 1, sz, fid ); bool sof0 = false; bool sos = false; this->sosIndex = 0; this->sosSize = 0; for ( int i = 0; i < (int)(sz - 8); ++i ) { if ( buffer[i] == 0xFF && buffer[i+1] == 0xC0) { fLastHeight = (buffer[i+5]<<5)|(buffer[i+6]>>3); fLastWidth = (buffer[i+7]<<5)|(buffer[i+8]>>3); if ( sos && sof0 ) break; } else if ( buffer[i] == 0xFF && buffer[i+1] == 0xDA ) { sosIndex = i + 2; if ( sos && sof0 ) break; } } if ( this->sosIndex > 0 ) this->sosSize = sz - this->sosIndex; printf( "Streaming image w=%d h=%d total_size=%d sos_size=%d\n", fLastWidth * 8, fLastHeight * 8, (int)sz, this->sosSize ); fclose(fFid); } TestJPEGVideoSource::~TestJPEGVideoSource() { if ( this->buffer ) delete [] buffer; } void TestJPEGVideoSource::doGetNextFrame() { fFrameSize = this->sosSize; if ( fFrameSize > fMaxSize ) { printf( "Truncating frame!!\n" ); fNumTruncatedBytes = fFrameSize - fMaxSize; fFrameSize = fMaxSize; } memcpy( fTo, this->buffer + this->sosIndex, fFrameSize ); if ( fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0 ) { gettimeofday( &fPresentationTime, NULL ); } else { unsigned uSeconds = fPresentationTime.tv_usec + ( fTimePerFrame * 1000 ); fPresentationTime.tv_sec += uSeconds / 1000000; fPresentationTime.tv_usec = uSeconds % 1000000; } fDurationInMicroseconds = fTimePerFrame * 1000; nextTask() = envir().taskScheduler().scheduleDelayedTask( 0, (TaskFunc*)FramedSource::afterGetting, this ); } u_int8_t TestJPEGVideoSource::type() { return 1; } u_int8_t TestJPEGVideoSource::qFactor() { return 65; } u_int8_t TestJPEGVideoSource::width() { return fLastWidth; } u_int8_t TestJPEGVideoSource::height() { return fLastHeight; }
_______________________________________________ live-devel mailing list live-devel@lists.live555.com http://lists.live555.com/mailman/listinfo/live-devel