diff --git a/src/zm_camera.cpp b/src/zm_camera.cpp index ddece6000..d1d2d0d49 100644 --- a/src/zm_camera.cpp +++ b/src/zm_camera.cpp @@ -39,8 +39,8 @@ Camera::Camera( type(p_type), width(p_width), height(p_height), - colours(p_colours), - subpixelorder(p_subpixelorder), + colours(ZM_COLOUR_RGB24), + subpixelorder(ZM_SUBPIX_ORDER_YUV420P), brightness(p_brightness), hue(p_hue), colour(p_colour), @@ -61,9 +61,9 @@ Camera::Camera( mLastAudioPTS(0), bytes(0), mIsPrimed(false) { - linesize = width * colours; + linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_YUVJ420P, width, 0), 32); // hardcoded hack pixels = width * height; - imagesize = static_cast(height) * linesize; + imagesize = av_image_get_buffer_size(AV_PIX_FMT_YUVJ420P, width, height, 32); // hardcoded hack Debug(2, "New camera id: %d width: %d line size: %d height: %d colours: %d subpixelorder: %d capture: %d, size: %llu", monitor->Id(), width, linesize, height, colours, subpixelorder, capture, imagesize); diff --git a/src/zm_event.cpp b/src/zm_event.cpp index e6d057952..b20e44b5c 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -304,9 +304,8 @@ bool Event::WriteFrameImage(Image *image, SystemTimePoint timestamp, const char Image ts_image(*image); monitor->TimestampImage(&ts_image, timestamp); return ts_image.WriteJpeg(event_file, mJpegCodecContext, mJpegSwsContext); - } else { - return image->WriteJpeg(event_file, mJpegCodecContext, mJpegSwsContext); } + return image->WriteJpeg(event_file, mJpegCodecContext, mJpegSwsContext); } bool Event::WritePacket(const std::shared_ptrpacket) { diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 6eb2adc79..684e0b39a 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -894,7 +894,6 @@ bool EventStream::sendFrame(Microseconds delta_us) { switch ( type ) { case STREAM_SINGLE : case STREAM_JPEG : - if ((!mJpegCodecContext) || (mJpegCodecContext->width != l_width || mJpegCodecContext->height != l_height)) { initContexts(l_width, l_height, config.jpeg_stream_quality); } diff --git a/src/zm_image.cpp b/src/zm_image.cpp index bb23bbee2..4ade753fe 100644 --- a/src/zm_image.cpp +++ b/src/zm_image.cpp @@ -174,7 +174,6 @@ Image::Image(int p_width, int p_height, int p_colours, int p_subpixelorder, uint if (!initialised) Initialise(); pixels = width * height; - linesize = p_width * p_colours; if (!subpixelorder and (colours>1)) { // Default to RGBA when no subpixelorder is specified. @@ -182,15 +181,14 @@ Image::Image(int p_width, int p_height, int p_colours, int p_subpixelorder, uint } imagePixFormat = AVPixFormat(); + linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), 32); + size = av_image_get_buffer_size(imagePixFormat, width, height, 32); if (p_buffer) { - size = linesize * height + padding; allocation = size; buffertype = ZM_BUFTYPE_DONTFREE; buffer = p_buffer; } else { - size = av_image_get_buffer_size(imagePixFormat, width, height, 32); - linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), 32); Debug(4, "line size: %d =? %d width %d Size %d ?= %d", linesize, av_image_get_linesize(imagePixFormat, width, 0), @@ -233,10 +231,10 @@ Image::Image(int p_width, int p_linesize, int p_height, int p_colours, int p_sub } Image::Image(const AVFrame *frame, int p_width, int p_height) : - colours(ZM_COLOUR_RGB32), + colours(ZM_COLOUR_RGB24), padding(0), - subpixelorder(ZM_SUBPIX_ORDER_RGBA), - imagePixFormat(AV_PIX_FMT_RGBA), + subpixelorder(ZM_SUBPIX_ORDER_YUV420P), + imagePixFormat(AV_PIX_FMT_YUVJ420P), buffer(0), holdbuffer(0) { width = (p_width == -1 ? frame->width : p_width); @@ -247,9 +245,9 @@ Image::Image(const AVFrame *frame, int p_width, int p_height) : // FIXME //(AVPixelFormat)frame->format; - size = av_image_get_buffer_size(AV_PIX_FMT_RGBA, width, height, 32); + size = av_image_get_buffer_size(AV_PIX_FMT_YUVJ420P, width, height, 32); // av_image_get_linesize isn't aligned, so we have to do that. - linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_RGBA, width, 0), 32); + linesize = FFALIGN(av_image_get_linesize(AV_PIX_FMT_YUVJ420P, width, 0), 32); AllocImgBuffer(size); this->Assign(frame); @@ -676,7 +674,7 @@ void Image::AssignDirect( return; } - size_t new_buffer_size = static_cast(p_width) * p_height * p_colours; + size_t new_buffer_size = static_cast(av_image_get_buffer_size(AV_PIX_FMT_YUVJ420P, width, height, 32)); // hardcoded hack if ( buffer_size < new_buffer_size ) { Error("Attempt to directly assign buffer from an undersized buffer of size: %zu, needed %dx%d*%d colours = %zu", @@ -707,8 +705,9 @@ void Image::AssignDirect( width = p_width; height = p_height; colours = p_colours; - linesize = width * colours; subpixelorder = p_subpixelorder; + imagePixFormat = AVPixFormat(); + linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), 32); pixels = width * height; size = new_buffer_size; update_function_pointers(); @@ -727,7 +726,7 @@ void Image::Assign( return; } - unsigned int new_size = p_width * p_height * p_colours; + unsigned int new_size = av_image_get_buffer_size(AV_PIX_FMT_YUVJ420P, width, height, 32); // hardcoded hack if ( buffer_size < new_size ) { Error("Attempt to assign buffer from an undersized buffer of size: %zu", buffer_size); return; @@ -762,6 +761,8 @@ void Image::Assign( pixels = width*height; colours = p_colours; subpixelorder = p_subpixelorder; + imagePixFormat = AVPixFormat(); + linesize = FFALIGN(av_image_get_linesize(imagePixFormat, width, 0), 32); size = new_size; } @@ -771,7 +772,7 @@ void Image::Assign( } void Image::Assign(const Image &image) { - unsigned int new_size = image.height * image.linesize; + unsigned int new_size = av_image_get_buffer_size(AV_PIX_FMT_YUVJ420P, width, height, 32); // hardcoded hack if ( image.buffer == nullptr ) { Error("Attempt to assign image with an empty buffer"); @@ -809,26 +810,14 @@ void Image::Assign(const Image &image) { pixels = width*height; colours = image.colours; subpixelorder = image.subpixelorder; + imagePixFormat = image.imagePixFormat; size = new_size; linesize = image.linesize; update_function_pointers(); } - if ( image.buffer != buffer ) { - if (image.linesize > linesize) { - Debug(1, "Must copy line by line due to different line size %d != %d", image.linesize, linesize); - uint8_t *src_ptr = image.buffer; - uint8_t *dst_ptr = buffer; - for (unsigned int i=0; i< image.height; i++) { - (*fptr_imgbufcpy)(dst_ptr, src_ptr, image.linesize); - src_ptr += image.linesize; - dst_ptr += linesize; - } - } else { - Debug(4, "Doing full copy line size %d != %d", image.linesize, linesize); - (*fptr_imgbufcpy)(buffer, image.buffer, size); - } - } + if ( image.buffer != buffer ) + (*fptr_imgbufcpy)(buffer, image.buffer, size); } Image *Image::HighlightEdges( @@ -1639,6 +1628,12 @@ bool Image::EncodeJpeg(JOCTET *outbuffer, int *outbuffer_size, AVCodecContext *p PopulateFrame(frame.get()); } + if (frame.get()->format != AV_PIX_FMT_YUV420P) { + Error("Jpeg frame format incorrect, got %d", frame.get()->format); + av_frame_unref(frame.get()); + return false; + } + pkt = av_packet_alloc(); avcodec_send_frame(p_jpegcodeccontext, frame.get()); @@ -5460,7 +5455,9 @@ __attribute__((noinline)) void std_deinterlace_4field_abgr(uint8_t* col1, uint8_ } AVPixelFormat Image::AVPixFormat() const { - if ( colours == ZM_COLOUR_RGB32 ) { + if ( subpixelorder == ZM_SUBPIX_ORDER_YUV420P) { + return AV_PIX_FMT_YUV420P; + } else if ( colours == ZM_COLOUR_RGB32 ) { return AV_PIX_FMT_RGBA; } else if ( colours == ZM_COLOUR_RGB24 ) { if ( subpixelorder == ZM_SUBPIX_ORDER_BGR) { diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 46a06bcf7..7d50ac883 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -2783,7 +2783,9 @@ bool Monitor::Decode() { int ret = packet->decode(camera->getVideoCodecContext()); if (ret > 0 and !zm_terminate) { if (packet->in_frame and !packet->image) { - packet->image = new Image(camera_width, camera_height, camera->Colours(), camera->SubpixelOrder()); + unsigned int subpix = packet->in_frame->format == AV_PIX_FMT_YUV420P ? ZM_SUBPIX_ORDER_YUV420P : camera->SubpixelOrder(); + unsigned int colours = packet->in_frame->format == AV_PIX_FMT_YUV420P ? ZM_COLOUR_RGB24 : camera->Colours(); + packet->image = new Image(camera_width, camera_height, colours, subpix); if (convert_context || this->setupConvertContext(packet->in_frame.get(), packet->image)) { if (!packet->image->Assign(packet->in_frame.get(), convert_context, dest_frame.get())) {