Remove all the scaling and conversion stuff. Use packet->decode. Set keyframe flag. return codes of functions are now -1 for failure, 0 for failure but no error and 1 for success.

This commit is contained in:
Isaac Connor 2020-12-27 12:02:02 -05:00
parent 7c9db96acc
commit 57542b01d5
2 changed files with 23 additions and 94 deletions

View File

@ -72,11 +72,7 @@ RemoteCameraRtsp::RemoteCameraRtsp(
mRawFrame = nullptr; mRawFrame = nullptr;
mFrame = nullptr; mFrame = nullptr;
frameCount = 0; frameCount = 0;
startTime=0;
#if HAVE_LIBSWSCALE
mConvertContext = nullptr;
#endif
/* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */
if ( colours == ZM_COLOUR_RGB32 ) { if ( colours == ZM_COLOUR_RGB32 ) {
subpixelorder = ZM_SUBPIX_ORDER_RGBA; subpixelorder = ZM_SUBPIX_ORDER_RGBA;
@ -96,13 +92,6 @@ RemoteCameraRtsp::~RemoteCameraRtsp() {
av_frame_free(&mFrame); av_frame_free(&mFrame);
av_frame_free(&mRawFrame); av_frame_free(&mRawFrame);
#if HAVE_LIBSWSCALE
if ( mConvertContext ) {
sws_freeContext(mConvertContext);
mConvertContext = nullptr;
}
#endif
if ( mCodecContext ) { if ( mCodecContext ) {
avcodec_close(mCodecContext); avcodec_close(mCodecContext);
mCodecContext = nullptr; // Freed by avformat_free_context in the destructor of RtspThread class mCodecContext = nullptr; // Freed by avformat_free_context in the destructor of RtspThread class
@ -167,7 +156,6 @@ int RemoteCameraRtsp::PrimeCapture() {
mVideoStreamId = -1; mVideoStreamId = -1;
mAudioStreamId = -1; mAudioStreamId = -1;
// Find the first video stream. // Find the first video stream.
for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) { for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) {
if ( is_video_stream(mFormatContext->streams[i]) ) { if ( is_video_stream(mFormatContext->streams[i]) ) {
@ -233,30 +221,8 @@ int RemoteCameraRtsp::PrimeCapture() {
Fatal("Image size mismatch. Required: %d Available: %d", pSize, imagesize); Fatal("Image size mismatch. Required: %d Available: %d", pSize, imagesize);
} }
#if HAVE_LIBSWSCALE return 1;
mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); } // end PrimeCapture
if ( mConvertContext == NULL )
Fatal( "Unable to create conversion context");
#else // HAVE_LIBSWSCALE
Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" );
#endif // HAVE_LIBSWSCALE
/*
#if HAVE_LIBSWSCALE
if(!sws_isSupportedInput(mCodecContext->pix_fmt)) {
Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff));
}
if(!sws_isSupportedOutput(imagePixFormat)) {
Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff));
}
#else // HAVE_LIBSWSCALE
Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" );
#endif // HAVE_LIBSWSCALE
*/
return 0;
}
int RemoteCameraRtsp::PreCapture() { int RemoteCameraRtsp::PreCapture() {
if ( !rtspThread->isRunning() ) if ( !rtspThread->isRunning() )
@ -265,21 +231,14 @@ int RemoteCameraRtsp::PreCapture() {
Error("Cannot precapture, no RTP sources"); Error("Cannot precapture, no RTP sources");
return -1; return -1;
} }
return 0; return 1;
} }
int RemoteCameraRtsp::Capture( ZMPacket &zm_packet ) { int RemoteCameraRtsp::Capture(ZMPacket &zm_packet) {
uint8_t* directbuffer; uint8_t* directbuffer;
int frameComplete = false; int frameComplete = false;
AVPacket *packet = &zm_packet.packet; AVPacket *packet = &zm_packet.packet;
/* Request a writeable buffer of the target image */
directbuffer = zm_packet.image->WriteBuffer(width, height, colours, subpixelorder);
if ( directbuffer == nullptr ) {
Error("Failed requesting writeable buffer for the captured image.");
return -1;
}
while ( !frameComplete ) { while ( !frameComplete ) {
buffer.clear(); buffer.clear();
if ( !rtspThread->isRunning() ) if ( !rtspThread->isRunning() )
@ -305,6 +264,8 @@ int RemoteCameraRtsp::Capture( ZMPacket &zm_packet ) {
lastPps = buffer; lastPps = buffer;
continue; continue;
} else if ( nalType == 5 ) { } else if ( nalType == 5 ) {
packet->flags |= AV_PKT_FLAG_KEY;
zm_packet.keyframe = 1;
// IDR // IDR
buffer += lastSps; buffer += lastSps;
buffer += lastPps; buffer += lastPps;
@ -315,57 +276,23 @@ int RemoteCameraRtsp::Capture( ZMPacket &zm_packet ) {
Debug(3, "Not an h264 packet"); Debug(3, "Not an h264 packet");
} }
// Don't need to do this... as zmPacket does it.
//av_init_packet( &packet );
while ( (!frameComplete) && (buffer.size() > 0) ) { while ( (!frameComplete) && (buffer.size() > 0) ) {
packet->data = buffer.head(); packet->data = buffer.head();
packet->size = buffer.size(); packet->size = buffer.size();
bytes += packet->size; bytes += packet->size;
// So I think this is the magic decode step. Result is a raw image? if ( 1 != zm_packet.decode(mCodecContext) ) {
int len = zm_send_packet_receive_frame(mCodecContext, mRawFrame, *packet);
if ( len < 0 ) {
Error("Error while decoding frame %d", frameCount); Error("Error while decoding frame %d", frameCount);
Hexdump(Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size()); Hexdump(Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size());
buffer.clear(); buffer.clear();
continue; break;
} }
int len = packet->size;
frameComplete = true; frameComplete = true;
Debug(2, "Frame: %d - %d/%d", frameCount, len, buffer.size()); Debug(2, "Frame: %d - %d/%d", frameCount, len, buffer.size());
buffer -= len; buffer -= len;
} }
// At this point, we either have a frame or ran out of buffer. What happens if we run out of buffer?
if ( frameComplete ) {
#if HAVE_LIBSWSCALE
if ( mConvertContext == nullptr ) {
mConvertContext = sws_getContext(
mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt,
width, height, imagePixFormat, SWS_BICUBIC, nullptr, nullptr, nullptr);
if ( mConvertContext == nullptr )
Fatal("Unable to create conversion context");
if (
((unsigned int)mRawFrame->width != width)
||
((unsigned int)mRawFrame->height != height)
) {
Warning("Monitor dimensions are %dx%d but camera is sending %dx%d",
width, height, mRawFrame->width, mRawFrame->height);
}
}
if ( sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize) < 0 )
Fatal("Unable to convert raw format %u to target format %u at frame %d",
mCodecContext->pix_fmt, imagePixFormat, frameCount );
#else // HAVE_LIBSWSCALE
Fatal("You must compile ffmpeg with the --enable-swscale option to use RTSP cameras");
#endif // HAVE_LIBSWSCALE
frameCount++;
} /* frame complete */
} /* getFrame() */ } /* getFrame() */
} // end while true } // end while true
@ -373,6 +300,6 @@ int RemoteCameraRtsp::Capture( ZMPacket &zm_packet ) {
} // end int RemoteCameraRtsp::Capture(ZMPacket &packet) } // end int RemoteCameraRtsp::Capture(ZMPacket &packet)
int RemoteCameraRtsp::PostCapture() { int RemoteCameraRtsp::PostCapture() {
return 0; return 1;
} }
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT

View File

@ -55,22 +55,12 @@ protected:
#if HAVE_LIBAVFORMAT #if HAVE_LIBAVFORMAT
AVFormatContext *mFormatContext; AVFormatContext *mFormatContext;
int mVideoStreamId;
int mAudioStreamId;
AVCodecContext *mCodecContext; AVCodecContext *mCodecContext;
AVCodec *mCodec; AVCodec *mCodec;
AVFrame *mRawFrame; AVFrame *mRawFrame;
AVFrame *mFrame; AVFrame *mFrame;
_AVPIXELFORMAT imagePixFormat; _AVPIXELFORMAT imagePixFormat;
#endif // HAVE_LIBAVFORMAT #endif // HAVE_LIBAVFORMAT
bool wasRecording;
VideoStore *videoStore;
char oldDirectory[4096];
int64_t startTime;
#if HAVE_LIBSWSCALE
struct SwsContext *mConvertContext;
#endif
public: public:
RemoteCameraRtsp( unsigned int p_monitor_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio ); RemoteCameraRtsp( unsigned int p_monitor_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, bool p_rtsp_describe, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
@ -86,6 +76,18 @@ public:
int Capture( ZMPacket &p ); int Capture( ZMPacket &p );
int PostCapture(); int PostCapture();
int Close() { return 0; }; int Close() { return 0; };
AVStream *get_VideoStream() {
if ( mVideoStreamId != -1 )
return mFormatContext->streams[mVideoStreamId];
return nullptr;
}
AVStream *get_AudioStream() {
if ( mAudioStreamId != -1 )
return mFormatContext->streams[mAudioStreamId];
return nullptr;
}
AVCodecContext *get_VideoCodecContext() { return mVideoCodecContext; };
AVCodecContext *get_AudioCodecContext() { return mAudioCodecContext; };
}; };
#endif // ZM_REMOTE_CAMERA_RTSP_H #endif // ZM_REMOTE_CAMERA_RTSP_H