Merge branch 'storageareas' of github.com:ConnorTechnology/ZoneMinder into storageareas

This commit is contained in:
Isaac Connor 2017-08-24 11:00:16 -04:00
commit de63aa8e8d
24 changed files with 1258 additions and 879 deletions

View File

@ -271,7 +271,7 @@ MAIN: while( $loop ) {
} # end foreach event
chdir( $Storage->Path() );
} # if USE_DEEP_STORAGE
Debug( 'Got '.int(keys(%$fs_events))." events for monitor $monitor_dir\n" );
Debug( 'Got '.int(keys(%$fs_events))." filesystem events for monitor $monitor_dir\n" );
#delete_empty_directories( $monitor_dir );
} # end foreach monitor
@ -351,7 +351,7 @@ MAIN: while( $loop ) {
if ( ! defined( $fs_events->{$db_event} ) ) {
Debug("Event $db_event is not in fs.");
my $Event = ZoneMinder::Event->find_one( Id=>$db_event );
if ( $Event ) {
if ( ! $Event ) {
Debug("Event $db_event is no longer in db. Filter probably deleted it while we were auditing.");
next;
}

View File

@ -143,11 +143,11 @@ while( 1 ) {
if ( !defined($image_time) ) {
# Can't read from shared data
$restart = 1;
Error( "Error reading shared data for $$monitor{id} $$monitor{Name}\n");
Error( "Error reading shared data for $$monitor{Id} $$monitor{Name}\n");
} elsif ( !$image_time ) {
# We can't get the last capture time so can't be sure it's died.
$restart = 1;
Error( "Error getting last capture time for $$monitor{id} $$monitor{Name}\n");
Error( "Error getting last capture time for $$monitor{Id} $$monitor{Name}\n");
} else {
my $max_image_delay = ( $monitor->{MaxFPS}
@ -159,7 +159,7 @@ while( 1 ) {
my $image_delay = $now-$image_time;
Debug( "Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay\n" );
if ( $image_delay > $max_image_delay ) {
Info( "Analysis daemon for $$monitor{id} $$monitor{Name} needs restarting,"
Info( "Analysis daemon for $$monitor{Id} $$monitor{Name} needs restarting,"
." time since last analysis $image_delay seconds ($now-$image_time)\n"
);
$restart = 1;
@ -167,7 +167,7 @@ while( 1 ) {
}
if ( $restart ) {
Info( "Restarting analysis daemon for $$monitor{id} $$monitor{Name}\n");
Info( "Restarting analysis daemon for $$monitor{Id} $$monitor{Name}\n");
my $command = "zmdc.pl restart zma -m ".$monitor->{Id};
runCommand( $command );
} # end if restart

View File

@ -4,7 +4,7 @@
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp)
# A fix for cmake recompiling the source files for every target.
add_library(zm STATIC ${ZM_BIN_SRC_FILES})

View File

@ -41,6 +41,7 @@
class Zone;
class Monitor;
class EventStream;
#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored
@ -191,81 +192,4 @@ class Event {
}
};
class EventStream : public StreamBase {
public:
typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode;
protected:
struct FrameData {
//unsigned long id;
time_t timestamp;
time_t offset;
double delta;
bool in_db;
};
struct EventData {
unsigned long event_id;
unsigned long monitor_id;
unsigned long storage_id;
unsigned long frame_count;
time_t start_time;
double duration;
char path[PATH_MAX];
int n_frames;
FrameData *frames;
char video_file[PATH_MAX];
};
protected:
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds
static const StreamMode DEFAULT_MODE = MODE_SINGLE;
protected:
StreamMode mode;
bool forceEventChange;
protected:
int curr_frame_id;
double curr_stream_time;
bool send_frame; // Used as a flag whether or not to send out a frame.
EventData *event_data;
protected:
bool loadEventData( int event_id );
bool loadInitialEventData( int init_event_id, unsigned int init_frame_id );
bool loadInitialEventData( int monitor_id, time_t event_time );
void checkEventLoaded();
void processCommand( const CmdMsg *msg );
bool sendFrame( int delta_us );
public:
EventStream() {
mode = DEFAULT_MODE;
forceEventChange = false;
curr_frame_id = 0;
curr_stream_time = 0.0;
event_data = 0;
}
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
loadInitialEventData( init_event_id, init_frame_id );
loadMonitor( event_data->monitor_id );
}
void setStreamStart( int monitor_id, time_t event_time ) {
loadInitialEventData( monitor_id, event_time );
loadMonitor( monitor_id );
}
void setStreamMode( StreamMode p_mode ) {
mode = p_mode;
}
void runStream();
Image *getImage();
};
#endif // ZM_EVENT_H

View File

@ -34,12 +34,11 @@
#include "zm_mpeg.h"
#include "zm_signal.h"
#include "zm_event.h"
#include "zm_eventstream.h"
#include "zm_storage.h"
#include "zm_monitor.h"
// sendfile tricks
extern "C" {
#include "zm_sendfile.h"
}
bool EventStream::loadInitialEventData( int monitor_id, time_t event_time ) {
static char sql[ZM_SQL_SML_BUFSIZ];
@ -138,6 +137,7 @@ bool EventStream::loadEventData( int event_id ) {
event_data->start_time = atoi(dbrow[3]);
event_data->duration = atof(dbrow[4]);
strncpy( event_data->video_file, dbrow[5], sizeof( event_data->video_file )-1 );
mysql_free_result( result );
Storage * storage = new Storage( event_data->storage_id );
const char *storage_path = storage->Path();
@ -160,7 +160,6 @@ bool EventStream::loadEventData( int event_id ) {
updateFrameRate( (double)event_data->frame_count/event_data->duration );
mysql_free_result( result );
snprintf( sql, sizeof(sql), "select FrameId, unix_timestamp( `TimeStamp` ), Delta from Frames where EventId = %d order by FrameId asc", event_id );
if ( mysql_query( &dbconn, sql ) ) {
@ -207,12 +206,23 @@ bool EventStream::loadEventData( int event_id ) {
exit( mysql_errno( &dbconn ) );
}
mysql_free_result( result );
//for ( int i = 0; i < 250; i++ )
//{
//Info( "%d -> %d @ %f (%d)", i+1, event_data->frames[i].timestamp, event_data->frames[i].delta, event_data->frames[i].in_db );
//Info( "%d -> %d @ %f (%d)", i+1, event_data->frames[i].timestamp, event_data->frames[i].delta, event_data->frames[i].in_db );
//}
mysql_free_result( result );
if ( event_data->video_file[0] ) {
char filepath[PATH_MAX];
snprintf( filepath, sizeof(filepath), "%s/%s", event_data->path, event_data->video_file );
ffmpeg_input = new FFmpeg_Input();
if ( 0 > ffmpeg_input->Open( filepath ) ) {
Warning("Unable to open ffmpeg_input %s/%s", event_data->path, event_data->video_file );
delete ffmpeg_input;
ffmpeg_input = NULL;
}
}
if ( forceEventChange || mode == MODE_ALL_GAPLESS ) {
if ( replay_rate > 0 )
@ -223,7 +233,7 @@ bool EventStream::loadEventData( int event_id ) {
Debug( 2, "Event:%ld, Frames:%ld, Duration: %.2f", event_data->event_id, event_data->frame_count, event_data->duration );
return( true );
}
} // bool EventStream::loadEventData( int event_id )
void EventStream::processCommand( const CmdMsg *msg ) {
Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] );
@ -590,11 +600,12 @@ bool EventStream::sendFrame( int delta_us ) {
} else if ( monitor->GetOptSaveJPEGs() & 2 ) {
snprintf( filepath, sizeof(filepath), Event::analyse_file_format, event_data->path, curr_frame_id );
if ( stat( filepath, &filestat ) < 0 ) {
Debug(1, "%s not found, dalling back to capture");
Debug(1, "analyze file %s not found will try to stream from other", filepath);
snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id );
filepath[0] = 0;
}
} else {
} else if ( ! ffmpeg_input ) {
Fatal("JPEGS not saved.zms is not capable of streaming jpegs from mp4 yet");
return false;
}
@ -619,7 +630,7 @@ bool EventStream::sendFrame( int delta_us ) {
int img_buffer_size = 0;
uint8_t *img_buffer = temp_img_buffer;
bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE));
bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)) && filepath[0];
fprintf( stdout, "--ZoneMinderFrame\r\n" );
@ -641,9 +652,27 @@ bool EventStream::sendFrame( int delta_us ) {
img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj );
#endif
} else {
Image image( filepath );
Image *image = NULL;
Image *send_image = prepareImage( &image );
if ( filepath[0] ) {
image = new Image( filepath );
} else if ( ffmpeg_input ) {
// Get the frame from the mp4 input
Debug(1,"Getting frame from ffmpeg");
AVFrame *frame = ffmpeg_input->get_frame( ffmpeg_input->get_video_stream_id() );
if ( frame ) {
image = new Image( frame );
av_frame_free(&frame);
} else {
Error("Failed getting a frame.");
return false;
}
} else {
Error("Unable to get a frame");
return false;
}
Image *send_image = prepareImage( image );
switch( type ) {
case STREAM_JPEG :
@ -667,6 +696,8 @@ bool EventStream::sendFrame( int delta_us ) {
Fatal( "Unexpected frame type %d", type );
break;
}
delete image;
image = NULL;
}
switch( type ) {
@ -685,7 +716,7 @@ bool EventStream::sendFrame( int delta_us ) {
}
if(send_raw) {
if ( send_raw ) {
#if HAVE_SENDFILE
fprintf( stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size );
if ( zm_sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size ) {
@ -705,6 +736,7 @@ bool EventStream::sendFrame( int delta_us ) {
#endif
fclose(fdj); /* Close the file handle */
} else {
Debug(3, "Content length: %d", img_buffer_size );
fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size );
if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) {
Error( "Unable to send stream frame: %s", strerror(errno) );
@ -721,11 +753,14 @@ bool EventStream::sendFrame( int delta_us ) {
void EventStream::runStream() {
Event::Initialise();
Debug(3, "Initialized");
openComms();
Debug(3, "Comms open");
checkInitialised();
Debug(3, "frame rate is: (%f)", (double)event_data->frame_count/event_data->duration );
updateFrameRate( (double)event_data->frame_count/event_data->duration );
if ( type == STREAM_JPEG )
@ -748,6 +783,7 @@ void EventStream::runStream() {
if ( step != 0 )
curr_frame_id += step;
// Detects when we hit end of event and will load the next event or previous event
checkEventLoaded();
// Get current frame data

View File

@ -26,79 +26,102 @@
#include "zm_image.h"
#include "zm_stream.h"
#include "zm_video.h"
#include "zm_ffmpeg_input.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavcodec/avcodec.h"
#ifdef __cplusplus
}
#endif
class EventStream : public StreamBase {
public:
typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode;
public:
typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode;
protected:
struct FrameData {
//unsigned long id;
time_t timestamp;
time_t offset;
double delta;
bool in_db;
};
protected:
struct FrameData {
//unsigned long id;
time_t timestamp;
time_t offset;
double delta;
bool in_db;
};
struct EventData {
unsigned long event_id;
unsigned long monitor_id;
unsigned long frame_count;
time_t start_time;
double duration;
char path[PATH_MAX];
int n_frames;
FrameData *frames;
char video_file[PATH_MAX];
};
struct EventData {
unsigned long event_id;
unsigned long monitor_id;
unsigned long storage_id;
unsigned long frame_count;
time_t start_time;
double duration;
char path[PATH_MAX];
int n_frames;
FrameData *frames;
char video_file[PATH_MAX];
};
protected:
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds
protected:
static const int STREAM_PAUSE_WAIT = 250000; // Microseconds
static const StreamMode DEFAULT_MODE = MODE_SINGLE;
static const StreamMode DEFAULT_MODE = MODE_SINGLE;
protected:
StreamMode mode;
bool forceEventChange;
StreamMode mode;
bool forceEventChange;
int curr_frame_id;
double curr_stream_time;
int curr_frame_id;
double curr_stream_time;
bool send_frame;
EventData *event_data;
EventData *event_data;
FFmpeg_Input *ffmpeg_input;
protected:
bool loadEventData( int event_id );
bool loadInitialEventData( int init_event_id, unsigned int init_frame_id );
bool loadInitialEventData( int monitor_id, time_t event_time );
protected:
bool loadEventData( int event_id );
bool loadInitialEventData( int init_event_id, unsigned int init_frame_id );
bool loadInitialEventData( int monitor_id, time_t event_time );
void checkEventLoaded();
void processCommand( const CmdMsg *msg );
bool sendFrame( int delta_us );
void checkEventLoaded();
void processCommand( const CmdMsg *msg );
bool sendFrame( int delta_us );
public:
EventStream() {
mode = DEFAULT_MODE;
public:
EventStream() {
mode = DEFAULT_MODE;
forceEventChange = false;
forceEventChange = false;
curr_frame_id = 0;
curr_stream_time = 0.0;
curr_frame_id = 0;
curr_stream_time = 0.0;
event_data = 0;
}
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
loadInitialEventData( init_event_id, init_frame_id );
loadMonitor( event_data->monitor_id );
}
void setStreamStart( int monitor_id, time_t event_time ) {
loadInitialEventData( monitor_id, event_time );
loadMonitor( monitor_id );
}
void setStreamMode( StreamMode p_mode ) {
mode = p_mode;
}
void runStream();
Image *getImage();
event_data = 0;
// Used when loading frames from an mp4
input_codec_context = 0;
input_codec = 0;
ffmpeg_input = NULL;
}
void setStreamStart( int init_event_id, unsigned int init_frame_id=0 ) {
loadInitialEventData( init_event_id, init_frame_id );
loadMonitor( event_data->monitor_id );
}
void setStreamStart( int monitor_id, time_t event_time ) {
loadInitialEventData( monitor_id, event_time );
loadMonitor( monitor_id );
}
void setStreamMode( StreamMode p_mode ) {
mode = p_mode;
}
void runStream();
Image *getImage();
private:
AVCodecContext *input_codec_context;
AVCodec *input_codec;
};
#endif // ZM_EVENTSTREAM_H

View File

@ -130,181 +130,6 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
#endif
#endif // HAVE_LIBAVUTIL
#if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
SWScale::SWScale() : gotdefaults(false), swscale_ctx(NULL), input_avframe(NULL), output_avframe(NULL) {
Debug(4,"SWScale object created");
/* Allocate AVFrame for the input */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
input_avframe = av_frame_alloc();
#else
input_avframe = avcodec_alloc_frame();
#endif
if(input_avframe == NULL) {
Fatal("Failed allocating AVFrame for the input");
}
/* Allocate AVFrame for the output */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
output_avframe = av_frame_alloc();
#else
output_avframe = avcodec_alloc_frame();
#endif
if(output_avframe == NULL) {
Fatal("Failed allocating AVFrame for the output");
}
}
SWScale::~SWScale() {
/* Free up everything */
av_frame_free( &input_avframe );
//input_avframe = NULL;
av_frame_free( &output_avframe );
//output_avframe = NULL;
if(swscale_ctx) {
sws_freeContext(swscale_ctx);
swscale_ctx = NULL;
}
Debug(4,"SWScale object destroyed");
}
int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
/* Assign the defaults */
default_input_pf = in_pf;
default_output_pf = out_pf;
default_width = width;
default_height = height;
gotdefaults = true;
return 0;
}
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
/* Parameter checking */
if(in_buffer == NULL || out_buffer == NULL) {
Error("NULL Input or output buffer");
return -1;
}
// if(in_pf == 0 || out_pf == 0) {
// Error("Invalid input or output pixel formats");
// return -2;
// }
if (!width || !height) {
Error("Invalid width or height");
return -3;
}
#if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0)
/* Warn if the input or output pixelformat is not supported */
if(!sws_isSupportedInput(in_pf)) {
Warning("swscale does not support the input format: %c%c%c%c",(in_pf)&0xff,((in_pf)&0xff),((in_pf>>16)&0xff),((in_pf>>24)&0xff));
}
if(!sws_isSupportedOutput(out_pf)) {
Warning("swscale does not support the output format: %c%c%c%c",(out_pf)&0xff,((out_pf>>8)&0xff),((out_pf>>16)&0xff),((out_pf>>24)&0xff));
}
#endif
/* Check the buffer sizes */
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t insize = av_image_get_buffer_size(in_pf, width, height,1);
#else
size_t insize = avpicture_get_size(in_pf, width, height);
#endif
if(insize != in_buffer_size) {
Error("The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size);
return -4;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1);
#else
size_t outsize = avpicture_get_size(out_pf, width, height);
#endif
if(outsize < out_buffer_size) {
Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size);
return -5;
}
/* Get the context */
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, width, height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
if(swscale_ctx == NULL) {
Error("Failed getting swscale context");
return -6;
}
/* Fill in the buffers */
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if (av_image_fill_arrays(input_avframe->data, input_avframe->linesize,
(uint8_t*) in_buffer, in_pf, width, height, 1) <= 0) {
#else
if (avpicture_fill((AVPicture*) input_avframe, (uint8_t*) in_buffer,
in_pf, width, height) <= 0) {
#endif
Error("Failed filling input frame with input buffer");
return -7;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
out_buffer, out_pf, width, height, 1) <= 0) {
#else
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, width,
height) <= 0) {
#endif
Error("Failed filling output frame with output buffer");
return -8;
}
/* Do the conversion */
if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) {
Error("swscale conversion failed");
return -10;
}
return 0;
}
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
return -12;
}
if(img->Height() != height) {
Error("Source image height differs. Source: %d Output: %d",img->Height(), height);
return -13;
}
return Convert(img->Buffer(),img->Size(),out_buffer,out_buffer_size,in_pf,out_pf,width,height);
}
int SWScale::ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(img,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
}
int SWScale::ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
}
#endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE
#if HAVE_LIBAVUTIL
@ -530,3 +355,33 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src ) {
}
#endif
bool is_video_stream( AVStream * stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
if ( stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO ) {
#else
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( stream->codec->codec_type == AVMEDIA_TYPE_VIDEO ) {
#else
if ( stream->codec->codec_type == CODEC_TYPE_VIDEO ) {
#endif
#endif
return true;
}
return false;
}
bool is_audio_stream( AVStream * stream ) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
if ( stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO ) {
#else
#if (LIBAVCODEC_VERSION_CHECK(52, 64, 0, 64, 0) || LIBAVUTIL_VERSION_CHECK(50, 14, 0, 14, 0))
if ( stream->codec->codec_type == AVMEDIA_TYPE_AUDIO ) {
#else
if ( stream->codec->codec_type == CODEC_TYPE_AUDIO ) {
#endif
#endif
return true;
}
return false;
}

View File

@ -21,11 +21,8 @@
#define ZM_FFMPEG_H
#include <stdint.h>
#include "zm.h"
#include "zm_image.h"
#ifdef __cplusplus
extern "C" {
#endif
// AVUTIL
#if HAVE_LIBAVUTIL_AVUTIL_H
@ -207,31 +204,6 @@ void FFMPEGInit();
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder);
#endif // HAVE_LIBAVUTIL
/* SWScale wrapper class to make our life easier and reduce code reuse */
#if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
class SWScale {
public:
SWScale();
~SWScale();
int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size);
int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size);
int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
protected:
bool gotdefaults;
struct SwsContext* swscale_ctx;
AVFrame* input_avframe;
AVFrame* output_avframe;
enum _AVPIXELFORMAT default_input_pf;
enum _AVPIXELFORMAT default_output_pf;
unsigned int default_width;
unsigned int default_height;
};
#endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
#if !LIBAVCODEC_VERSION_CHECK(54, 25, 0, 51, 100)
#define AV_CODEC_ID_NONE CODEC_ID_NONE
#define AV_CODEC_ID_PCM_MULAW CODEC_ID_PCM_MULAW
@ -353,4 +325,6 @@ unsigned int zm_av_packet_ref( AVPacket *dst, AVPacket *src );
int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt);
bool is_video_stream( AVStream * stream );
bool is_audio_stream( AVStream * stream );
#endif // ZM_FFMPEG_H

View File

@ -290,7 +290,7 @@ int FfmpegCamera::Capture( Image &image ) {
/* Request a writeable buffer of the target image */
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
if(directbuffer == NULL) {
if ( directbuffer == NULL ) {
Error("Failed requesting writeable buffer for the captured image.");
return (-1);
}
@ -304,17 +304,6 @@ int FfmpegCamera::Capture( Image &image ) {
#endif
#if HAVE_LIBSWSCALE
if ( mConvertContext == NULL ) {
mConvertContext = sws_getContext(mVideoCodecContext->width,
mVideoCodecContext->height,
mVideoCodecContext->pix_fmt,
width, height, imagePixFormat,
SWS_BICUBIC, NULL, NULL, NULL);
if ( mConvertContext == NULL )
Fatal( "Unable to create conversion context for %s", mPath.c_str() );
}
if ( sws_scale(mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mVideoCodecContext->height, mFrame->data, mFrame->linesize) < 0 )
Fatal("Unable to convert raw format %u to target format %u at frame %d", mVideoCodecContext->pix_fmt, imagePixFormat, frameCount);
#else // HAVE_LIBSWSCALE

178
src/zm_ffmpeg_input.cpp Normal file
View File

@ -0,0 +1,178 @@
#include "zm_ffmpeg_input.h"
#include "zm_logger.h"
#include "zm_ffmpeg.h"
FFmpeg_Input::FFmpeg_Input() {
input_format_context = NULL;
video_stream_id = -1;
audio_stream_id = -1;
av_register_all();
avcodec_register_all();
}
FFmpeg_Input::~FFmpeg_Input() {
}
int FFmpeg_Input::Open( const char *filepath ) {
int error;
/** Open the input file to read from it. */
if ( (error = avformat_open_input( &input_format_context, filepath, NULL, NULL)) < 0 ) {
Error("Could not open input file '%s' (error '%s')\n",
filepath, av_make_error_string(error).c_str() );
input_format_context = NULL;
return error;
}
/** Get information on the input file (number of streams etc.). */
if ( (error = avformat_find_stream_info(input_format_context, NULL)) < 0 ) {
Error( "Could not open find stream info (error '%s')\n",
av_make_error_string(error).c_str() );
avformat_close_input(&input_format_context);
return error;
}
for ( unsigned int i = 0; i < input_format_context->nb_streams; i += 1 ) {
if ( is_video_stream( input_format_context->streams[i] ) ) {
zm_dump_stream_format(input_format_context, i, 0, 0);
if ( video_stream_id == -1 ) {
video_stream_id = i;
// if we break, then we won't find the audio stream
} else {
Warning( "Have another video stream." );
}
} else if ( is_audio_stream( input_format_context->streams[i] ) ) {
if ( audio_stream_id == -1 ) {
audio_stream_id = i;
} else {
Warning( "Have another audio stream." );
}
}
streams[i].frame_count = 0;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
streams[i].context = avcodec_alloc_context3( NULL );
avcodec_parameters_to_context( streams[i].context, input_format_context->streams[i]->codecpar );
#else
streams[i].context = input_format_context->streams[i]->codec;
#endif
if ( !(streams[i].codec = avcodec_find_decoder(streams[i].context->codec_id)) ) {
Error( "Could not find input codec\n");
avformat_close_input(&input_format_context);
return AVERROR_EXIT;
} else {
Debug(1, "Using codec (%s) for stream %d", streams[i].codec->name, i );
}
if ((error = avcodec_open2( streams[i].context, streams[i].codec, NULL)) < 0) {
Error( "Could not open input codec (error '%s')\n",
av_make_error_string(error).c_str() );
avcodec_free_context( &streams[i].context );
avformat_close_input(&input_format_context);
return error;
}
} // end foreach stream
if ( video_stream_id == -1 )
Error( "Unable to locate video stream in %s", filepath );
if ( audio_stream_id == -1 )
Debug( 3, "Unable to locate audio stream in %s", filepath );
return 0;
} // end int FFmpeg_Input::Open( const char * filepath )
AVFrame *FFmpeg_Input::get_frame( int stream_id ) {
Debug(1, "Getting frame from stream %d", stream_id );
int frameComplete = false;
AVPacket packet;
av_init_packet( &packet );
AVFrame *frame = zm_av_frame_alloc();
char errbuf[AV_ERROR_MAX_STRING_SIZE];
while ( !frameComplete ) {
int ret = av_read_frame( input_format_context, &packet );
if ( ret < 0 ) {
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
if (
// Check if EOF.
(ret == AVERROR_EOF || (input_format_context->pb && input_format_context->pb->eof_reached)) ||
// Check for Connection failure.
(ret == -110)
) {
Info( "av_read_frame returned %s.", errbuf );
return NULL;
}
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret, errbuf );
return NULL;
}
if ( (stream_id < 0 ) || ( packet.stream_index == stream_id ) ) {
Debug(1,"Packet is for our stream (%d)", packet.stream_index );
AVCodecContext *context = streams[packet.stream_index].context;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
ret = avcodec_send_packet( context, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
zm_av_packet_unref( &packet );
continue;
} else {
Debug(1, "Success getting a packet");
}
#if HAVE_AVUTIL_HWCONTEXT_H
if ( hwaccel ) {
ret = avcodec_receive_frame( context, hwFrame );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to receive frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
zm_av_packet_unref( &packet );
continue;
}
ret = av_hwframe_transfer_data(frame, hwFrame, 0);
if (ret < 0) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to transfer frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
zm_av_packet_unref( &packet );
continue;
}
} else {
#endif
Debug(1,"Getting a frame?");
ret = avcodec_receive_frame( context, frame );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to send packet at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
zm_av_packet_unref( &packet );
continue;
}
#if HAVE_AVUTIL_HWCONTEXT_H
}
#endif
frameComplete = 1;
# else
ret = zm_avcodec_decode_video( streams[packet.stream_index].context, frame, &frameComplete, &packet );
if ( ret < 0 ) {
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
Error( "Unable to decode frame at frame %d: %s, continuing", streams[packet.stream_index].frame_count, errbuf );
zm_av_packet_unref( &packet );
continue;
}
#endif
} // end if it's the right stream
zm_av_packet_unref( &packet );
} // end while ! frameComplete
return frame;
} // end AVFrame *FFmpeg_Input::get_frame

45
src/zm_ffmpeg_input.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef ZM_FFMPEG_INPUT_H
#define ZM_FFMPEG_INPUT_H
#ifdef __cplusplus
extern "C" {
#endif
#include "libavformat/avformat.h"
#include "libavformat/avio.h"
#include "libavcodec/avcodec.h"
#ifdef __cplusplus
}
#endif
class FFmpeg_Input {
public:
FFmpeg_Input();
~FFmpeg_Input();
int Open( const char *filename );
int Close();
AVFrame *get_frame( int stream_id=-1 );
int get_video_stream_id() {
return video_stream_id;
}
int get_audio_stream_id() {
return audio_stream_id;
}
private:
typedef struct {
AVCodecContext *context;
AVCodec *codec;
int frame_count;
} stream;
stream streams[2];
int video_stream_id;
int audio_stream_id;
AVFormatContext *input_format_context;
};
#endif

View File

@ -22,6 +22,7 @@
#include "zm_image.h"
#include "zm_utils.h"
#include "zm_rgb.h"
#include "zm_ffmpeg.h"
#include <sys/stat.h>
#include <errno.h>
@ -128,6 +129,46 @@ Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uin
text[0] = '\0';
}
Image::Image( const AVFrame *frame ) {
AVFrame *dest_frame = zm_av_frame_alloc();
width = frame->width;
height = frame->height;
pixels = width*height;
colours = ZM_COLOUR_RGB32;
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
size = pixels*colours;
buffer = 0;
holdbuffer = 0;
AllocImgBuffer(size);
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(dest_frame->data, dest_frame->linesize,
buffer, AV_PIX_FMT_RGBA, width, height, 1);
#else
avpicture_fill( (AVPicture *)mFrame, buffer,
AV_PIX_FMT_RGBA, width, height);
#endif
#if HAVE_LIBSWSCALE
struct SwsContext *mConvertContext = sws_getContext(
width,
height,
(AVPixelFormat)frame->format,
width, height,
AV_PIX_FMT_RGBA, SWS_BICUBIC, NULL,
NULL, NULL);
if ( mConvertContext == NULL )
Fatal( "Unable to create conversion context" );
if ( sws_scale(mConvertContext, frame->data, frame->linesize, 0, frame->height, dest_frame->data, dest_frame->linesize) < 0 )
Fatal("Unable to convert raw format %u to target format %u", frame->format, AV_PIX_FMT_RGBA);
#else // HAVE_LIBSWSCALE
Fatal("You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras");
#endif // HAVE_LIBSWSCALE
av_frame_free( &dest_frame );
}
Image::Image( const Image &p_image ) {
if ( !initialised )
Initialise();

View File

@ -21,8 +21,7 @@
#define ZM_IMAGE_H
#include "zm.h"
extern "C"
{
extern "C" {
#include "zm_jpeg.h"
}
#include "zm_rgb.h"
@ -32,6 +31,9 @@ extern "C"
#include "zm_mem_utils.h"
#include "zm_utils.h"
class Image;
#include "zm_ffmpeg.h"
#include <errno.h>
#if HAVE_ZLIB_H
@ -148,12 +150,12 @@ protected:
int holdbuffer; /* Hold the buffer instead of replacing it with new one */
char text[1024];
public:
Image();
Image( const char *filename );
Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0);
Image( const Image &p_image );
Image( const AVFrame *frame );
~Image();
static void Initialise();
static void Deinitialise();

View File

@ -29,6 +29,7 @@
#include "zm_signal.h"
#include "zm_monitor.h"
#include "zm_video.h"
#include "zm_eventstream.h"
#if ZM_HAS_V4L
#include "zm_local_camera.h"
#endif // ZM_HAS_V4L

View File

@ -20,6 +20,8 @@
#include "zm_packet.h"
#include "zm_ffmpeg.h"
#include <sys/time.h>
using namespace std;
ZMPacket::ZMPacket( AVPacket *p ) {

View File

@ -19,12 +19,11 @@
#include "zm_packetqueue.h"
#include "zm_ffmpeg.h"
#include <sys/time.h>
#define VIDEO_QUEUESIZE 200
#define AUDIO_QUEUESIZE 50
using namespace std;
zm_packetqueue::zm_packetqueue(){
}
@ -68,7 +67,7 @@ unsigned int zm_packetqueue::clearQueue( unsigned int frames_to_keep, int stream
return 0;
}
list<ZMPacket *>::reverse_iterator it;
std::list<ZMPacket *>::reverse_iterator it;
ZMPacket *packet = NULL;
for ( it = pktQueue.rbegin(); it != pktQueue.rend() && frames_to_keep; ++it ) {
@ -121,7 +120,7 @@ void zm_packetqueue::clear_unwanted_packets( timeval *recording_started, int mVi
// Step 1 - find keyframe < recording_started.
// Step 2 - pop packets until we get to the packet in step 2
list<ZMPacket *>::reverse_iterator it;
std::list<ZMPacket *>::reverse_iterator it;
Debug(3, "Looking for keyframe after start recording stream id (%d)", mVideoStreamId );
for ( it = pktQueue.rbegin(); it != pktQueue.rend(); ++ it ) {

View File

@ -1,3 +1,10 @@
#ifndef ZM_SENDFILE_H
#define ZM_SENDFILE_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HAVE_SENDFILE4_SUPPORT
#include <sys/sendfile.h>
int zm_sendfile(int out_fd, int in_fd, off_t *offset, size_t size) {
@ -29,3 +36,9 @@ int zm_sendfile(int out_fd, int in_fd, off_t *offset, off_t size) {
#else
#error "Your platform does not support sendfile. Sorry."
#endif
#ifdef __cplusplus
}
#endif
#endif

198
src/zm_swscale.cpp Normal file
View File

@ -0,0 +1,198 @@
/*
* ZoneMinder FFMPEG implementation, $Date$, $Revision$
* Copyright (C) 2001-2008 Philip Coombes
*
* 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 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "zm_ffmpeg.h"
#include "zm_image.h"
#include "zm_rgb.h"
#include "zm_swscale.h"
#if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
SWScale::SWScale() : gotdefaults(false), swscale_ctx(NULL), input_avframe(NULL), output_avframe(NULL) {
Debug(4,"SWScale object created");
/* Allocate AVFrame for the input */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
input_avframe = av_frame_alloc();
#else
input_avframe = avcodec_alloc_frame();
#endif
if(input_avframe == NULL) {
Fatal("Failed allocating AVFrame for the input");
}
/* Allocate AVFrame for the output */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
output_avframe = av_frame_alloc();
#else
output_avframe = avcodec_alloc_frame();
#endif
if(output_avframe == NULL) {
Fatal("Failed allocating AVFrame for the output");
}
}
SWScale::~SWScale() {
/* Free up everything */
av_frame_free( &input_avframe );
//input_avframe = NULL;
av_frame_free( &output_avframe );
//output_avframe = NULL;
if(swscale_ctx) {
sws_freeContext(swscale_ctx);
swscale_ctx = NULL;
}
Debug(4,"SWScale object destroyed");
}
int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
/* Assign the defaults */
default_input_pf = in_pf;
default_output_pf = out_pf;
default_width = width;
default_height = height;
gotdefaults = true;
return 0;
}
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
/* Parameter checking */
if(in_buffer == NULL || out_buffer == NULL) {
Error("NULL Input or output buffer");
return -1;
}
// if(in_pf == 0 || out_pf == 0) {
// Error("Invalid input or output pixel formats");
// return -2;
// }
if (!width || !height) {
Error("Invalid width or height");
return -3;
}
#if LIBSWSCALE_VERSION_CHECK(0, 8, 0, 8, 0)
/* Warn if the input or output pixelformat is not supported */
if(!sws_isSupportedInput(in_pf)) {
Warning("swscale does not support the input format: %c%c%c%c",(in_pf)&0xff,((in_pf)&0xff),((in_pf>>16)&0xff),((in_pf>>24)&0xff));
}
if(!sws_isSupportedOutput(out_pf)) {
Warning("swscale does not support the output format: %c%c%c%c",(out_pf)&0xff,((out_pf>>8)&0xff),((out_pf>>16)&0xff),((out_pf>>24)&0xff));
}
#endif
/* Check the buffer sizes */
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t insize = av_image_get_buffer_size(in_pf, width, height,1);
#else
size_t insize = avpicture_get_size(in_pf, width, height);
#endif
if(insize != in_buffer_size) {
Error("The input buffer size does not match the expected size for the input format. Required: %d Available: %d", insize, in_buffer_size);
return -4;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1);
#else
size_t outsize = avpicture_get_size(out_pf, width, height);
#endif
if(outsize < out_buffer_size) {
Error("The output buffer is undersized for the output format. Required: %d Available: %d", outsize, out_buffer_size);
return -5;
}
/* Get the context */
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, width, height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
if(swscale_ctx == NULL) {
Error("Failed getting swscale context");
return -6;
}
/* Fill in the buffers */
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if (av_image_fill_arrays(input_avframe->data, input_avframe->linesize,
(uint8_t*) in_buffer, in_pf, width, height, 1) <= 0) {
#else
if (avpicture_fill((AVPicture*) input_avframe, (uint8_t*) in_buffer,
in_pf, width, height) <= 0) {
#endif
Error("Failed filling input frame with input buffer");
return -7;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
out_buffer, out_pf, width, height, 1) <= 0) {
#else
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, width,
height) <= 0) {
#endif
Error("Failed filling output frame with output buffer");
return -8;
}
/* Do the conversion */
if(!sws_scale(swscale_ctx, input_avframe->data, input_avframe->linesize, 0, height, output_avframe->data, output_avframe->linesize ) ) {
Error("swscale conversion failed");
return -10;
}
return 0;
}
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);
return -12;
}
if(img->Height() != height) {
Error("Source image height differs. Source: %d Output: %d",img->Height(), height);
return -13;
}
return Convert(img->Buffer(),img->Size(),out_buffer,out_buffer_size,in_pf,out_pf,width,height);
}
int SWScale::ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(img,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
}
int SWScale::ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size) {
if(!gotdefaults) {
Error("Defaults are not set");
return -24;
}
return Convert(in_buffer,in_buffer_size,out_buffer,out_buffer_size,default_input_pf,default_output_pf,default_width,default_height);
}
#endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL

31
src/zm_swscale.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef ZM_SWSCALE_H
#define ZM_SWSCALE_H
#include "zm_image.h"
#include "zm_ffmpeg.h"
/* SWScale wrapper class to make our life easier and reduce code reuse */
#if HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
class SWScale {
public:
SWScale();
~SWScale();
int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size);
int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size);
int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
protected:
bool gotdefaults;
struct SwsContext* swscale_ctx;
AVFrame* input_avframe;
AVFrame* output_avframe;
enum _AVPIXELFORMAT default_input_pf;
enum _AVPIXELFORMAT default_output_pf;
unsigned int default_width;
unsigned int default_height;
};
#endif // HAVE_LIBSWSCALE && HAVE_LIBAVUTIL
#endif

View File

@ -21,6 +21,7 @@
#include "zm_utils.h"
#include "zm_ffmpeg.h"
#include "zm_buffer.h"
#include "zm_swscale.h"
/*
#define HAVE_LIBX264 1

File diff suppressed because it is too large Load Diff

View File

@ -18,35 +18,35 @@ class VideoStore {
private:
unsigned int packets_written;
AVOutputFormat *output_format;
AVOutputFormat *out_format;
AVFormatContext *oc;
AVStream *video_output_stream;
AVStream *audio_output_stream;
AVCodecContext *video_output_context;
AVStream *video_out_stream;
AVStream *audio_out_stream;
AVCodecContext *video_out_ctx;
AVStream *video_input_stream;
AVStream *audio_input_stream;
AVStream *video_in_stream;
AVStream *audio_in_stream;
// Move this into the object so that we aren't constantly allocating/deallocating it on the stack
AVPacket opkt;
// we are transcoding
AVFrame *input_frame;
AVFrame *output_frame;
AVFrame *in_frame;
AVFrame *out_frame;
AVCodecContext *video_input_context;
AVCodecContext *audio_input_context;
AVCodecContext *video_in_ctx;
AVCodecContext *audio_in_ctx;
int ret;
// The following are used when encoding the audio stream to AAC
AVCodec *audio_output_codec;
AVCodecContext *audio_output_context;
AVCodec *audio_out_codec;
AVCodecContext *audio_out_ctx;
int data_present;
AVAudioFifo *fifo;
int output_frame_size;
int out_frame_size;
#ifdef HAVE_LIBAVRESAMPLE
AVAudioResampleContext* resample_context;
AVAudioResampleContext* resample_ctx;
#endif
uint8_t *converted_input_samples;
uint8_t *converted_in_samples;
const char *filename;
const char *format;
@ -54,13 +54,13 @@ AVAudioResampleContext* resample_context;
bool keyframeMessage;
int keyframeSkipNumber;
// These are for input
// These are for in
int64_t video_last_pts;
int64_t video_last_dts;
int64_t audio_last_pts;
int64_t audio_last_dts;
// These are for output, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
// These are for out, should start at zero. We assume they do not wrap because we just aren't going to save files that big.
int64_t video_next_pts;
int64_t video_next_dts;
int64_t audio_next_pts;
@ -71,7 +71,13 @@ AVAudioResampleContext* resample_context;
bool setup_resampler();
public:
VideoStore(const char *filename_in, const char *format_in, AVStream *video_input_stream, AVStream *audio_input_stream, int64_t nStartTime, Monitor * p_monitor );
VideoStore(
const char *filename_in,
const char *format_in,
AVStream *video_in_stream,
AVStream *audio_in_stream,
int64_t nStartTime,
Monitor * p_monitor);
~VideoStore();
int writeVideoFramePacket( AVPacket *pkt );

View File

@ -26,6 +26,7 @@
#include "zm_signal.h"
#include "zm_monitor.h"
#include "zm_monitorstream.h"
#include "zm_eventstream.h"
bool ValidateAccess( User *user, int mon_id ) {
bool allowed = true;
@ -51,7 +52,7 @@ int main( int argc, const char *argv[] ) {
srand( getpid() * time( 0 ) );
enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR;
enum { ZMS_UNKNOWN, ZMS_MONITOR, ZMS_EVENT } source = ZMS_UNKNOWN;
enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG;
char format[32] = "";
int monitor_id = 0;
@ -120,12 +121,16 @@ int main( int argc, const char *argv[] ) {
strncpy( format, value, sizeof(format) );
} else if ( !strcmp( name, "monitor" ) ) {
monitor_id = atoi( value );
if ( source == ZMS_UNKNOWN )
source = ZMS_MONITOR;
} else if ( !strcmp( name, "time" ) ) {
event_time = atoi( value );
} else if ( !strcmp( name, "event" ) ) {
event_id = strtoull( value, (char **)NULL, 10 );
source = ZMS_EVENT;
} else if ( !strcmp( name, "frame" ) ) {
frame_id = strtoull( value, (char **)NULL, 10 );
source = ZMS_EVENT;
} else if ( !strcmp( name, "scale" ) ) {
scale = atoi( value );
} else if ( !strcmp( name, "rate" ) ) {
@ -263,6 +268,7 @@ int main( int argc, const char *argv[] ) {
if ( ! event_id ) {
Fatal( "Can't view an event without specifying an event_id." );
}
Debug(3,"Doing event stream scale(%d)", scale );
EventStream stream;
stream.setStreamScale( scale );
stream.setStreamReplayRate( rate );
@ -272,6 +278,7 @@ int main( int argc, const char *argv[] ) {
if ( monitor_id && event_time ) {
stream.setStreamStart( monitor_id, event_time );
} else {
Debug(3, "Setting stream start to frame (%d)", frame_id);
stream.setStreamStart( event_id, frame_id );
}
if ( mode == ZMS_JPEG ) {
@ -290,6 +297,8 @@ int main( int argc, const char *argv[] ) {
#endif // HAVE_LIBAVCODEC
} // end if jpeg or mpeg
stream.runStream();
} else {
Error("Neither a monitor or event was specified.");
} // end if monitor or event
logTerm();

View File

@ -131,7 +131,7 @@ class Event {
} # end Event->delete
public function getStreamSrc( $args=array(), $querySep='&amp;' ) {
if ( $this->{'DefaultVideo'} ) {
if ( $this->{'DefaultVideo'} and $args['mode'] != 'jpeg' ) {
return ( ZM_BASE_PATH != '/' ? ZM_BASE_PATH : '' ).'/index.php?view=view_video&eid='.$this->{'Id'};
}