mirror of
https://github.com/Motion-Project/motion.git
synced 2026-05-18 03:24:38 -04:00
Change to C++
This commit is contained in:
780
src/util.cpp
Normal file
780
src/util.cpp
Normal file
@@ -0,0 +1,780 @@
|
||||
/* util.cpp
|
||||
*
|
||||
* This file is part of the Motion application
|
||||
* Copyright (C) 2019 Motion-Project Developers(motion-project.github.io)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "motion.hpp"
|
||||
#include "util.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "dbse.hpp" /*For dbse ID in format output */
|
||||
|
||||
|
||||
/** Non case sensitive equality check for strings*/
|
||||
int mystrceq(const char* var1, const char* var2){
|
||||
return (strcasecmp(var1,var2) ? 0 : 1);
|
||||
}
|
||||
|
||||
/** Non case sensitive inequality check for strings*/
|
||||
int mystrcne(const char* var1, const char* var2){
|
||||
return (strcasecmp(var1,var2) ? 1: 0);
|
||||
}
|
||||
|
||||
/** Case sensitive equality check for strings*/
|
||||
int mystreq(const char* var1, const char* var2){
|
||||
return (strcmp(var1,var2) ? 0 : 1);
|
||||
}
|
||||
|
||||
/** Case sensitive inequality check for strings*/
|
||||
int mystrne(const char* var1, const char* var2){
|
||||
return (strcmp(var1,var2) ? 1: 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* mymalloc
|
||||
*
|
||||
* Allocates some memory and checks if that succeeded or not. If it failed,
|
||||
* do some errorlogging and bail out.
|
||||
*
|
||||
* NOTE: Kenneth Lavrsen changed printing of size_t types so instead of using
|
||||
* conversion specifier %zd I changed it to %llu and casted the size_t
|
||||
* variable to unsigned long long. The reason for this nonsense is that older
|
||||
* versions of gcc like 2.95 uses %Zd and does not understand %zd. So to avoid
|
||||
* this mess I used a more generic way. Long long should have enough bits for
|
||||
* 64-bit machines with large memory areas.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* nbytes - no. of bytes to allocate
|
||||
*
|
||||
* Returns: a pointer to the allocated memory
|
||||
*/
|
||||
void * mymalloc(size_t nbytes)
|
||||
{
|
||||
void *dummy = calloc(nbytes, 1);
|
||||
|
||||
if (!dummy) {
|
||||
MOTION_LOG(EMG, TYPE_ALL, SHOW_ERRNO, _("Could not allocate %llu bytes of memory!")
|
||||
,(unsigned long long)nbytes);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
/**
|
||||
* myrealloc
|
||||
*
|
||||
* Re-allocate (i.e., resize) some memory and check if that succeeded or not.
|
||||
* If it failed, do some errorlogging and bail out. If the new memory size
|
||||
* is 0, the memory is freed.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* ptr - pointer to the memory to resize/reallocate
|
||||
* size - new memory size
|
||||
* desc - name of the calling function
|
||||
*
|
||||
* Returns: a pointer to the reallocated memory, or NULL if the memory was
|
||||
* freed
|
||||
*/
|
||||
void *myrealloc(void *ptr, size_t size, const char *desc)
|
||||
{
|
||||
void *dummy = NULL;
|
||||
|
||||
if (size == 0) {
|
||||
free(ptr);
|
||||
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO
|
||||
,_("Warning! Function %s tries to resize memoryblock at %p to 0 bytes!")
|
||||
,desc, ptr);
|
||||
} else {
|
||||
dummy = realloc(ptr, size);
|
||||
if (!dummy) {
|
||||
MOTION_LOG(EMG, TYPE_ALL, NO_ERRNO
|
||||
,_("Could not resize memory-block at offset %p to %llu bytes (function %s)!")
|
||||
,ptr, (unsigned long long)size, desc);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mycreate_path
|
||||
*
|
||||
* This function creates a whole path, like mkdir -p. Example paths:
|
||||
* this/is/an/example/
|
||||
* /this/is/an/example/
|
||||
* Warning: a path *must* end with a slash!
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cam - current thread's context structure (for logging)
|
||||
* path - the path to create
|
||||
*
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int mycreate_path(const char *path)
|
||||
{
|
||||
char *start;
|
||||
mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
|
||||
|
||||
if (path[0] == '/')
|
||||
start = (char*)strchr(path + 1, '/');
|
||||
else
|
||||
start = (char*)strchr(path, '/');
|
||||
|
||||
while (start) {
|
||||
char *buffer = mystrdup(path);
|
||||
buffer[start-path] = 0x00;
|
||||
|
||||
if (mkdir(buffer, mode) == -1 && errno != EEXIST) {
|
||||
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO
|
||||
,_("Problem creating directory %s"), buffer);
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
start = strchr(start + 1, '/');
|
||||
|
||||
if (!start)
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("creating directory %s"), buffer);
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* myfopen
|
||||
*
|
||||
* This function opens a file, if that failed because of an ENOENT error
|
||||
* (which is: path does not exist), the path is created and then things are
|
||||
* tried again. This is faster then trying to create that path over and over
|
||||
* again. If someone removes the path after it was created, myfopen will
|
||||
* recreate the path automatically.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* path - path to the file to open
|
||||
* mode - open mode
|
||||
*
|
||||
* Returns: the file stream object
|
||||
*/
|
||||
FILE * myfopen(const char *path, const char *mode)
|
||||
{
|
||||
/* first, just try to open the file */
|
||||
FILE *dummy = fopen(path, mode);
|
||||
if (dummy) return dummy;
|
||||
|
||||
/* could not open file... */
|
||||
/* path did not exist? */
|
||||
if (errno == ENOENT) {
|
||||
|
||||
/* create path for file... */
|
||||
if (mycreate_path(path) == -1)
|
||||
return NULL;
|
||||
|
||||
/* and retry opening the file */
|
||||
dummy = fopen(path, mode);
|
||||
}
|
||||
if (!dummy) {
|
||||
/*
|
||||
* Two possibilities
|
||||
* 1: there was an other error while trying to open the file for the
|
||||
* first time
|
||||
* 2: could still not open the file after the path was created
|
||||
*/
|
||||
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO
|
||||
,_("Error opening file %s with mode %s"), path, mode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
/**
|
||||
* myfclose
|
||||
*
|
||||
* Motion-specific variant of fclose()
|
||||
*
|
||||
* Returns: fclose() return value
|
||||
*/
|
||||
int myfclose(FILE* fh)
|
||||
{
|
||||
int rval = fclose(fh);
|
||||
|
||||
if (rval != 0)
|
||||
MOTION_LOG(ERR, TYPE_ALL, SHOW_ERRNO, _("Error closing file"));
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* mystrftime_long
|
||||
*
|
||||
* Motion-specific long form of format specifiers.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cam - current thread's context structure.
|
||||
* width - width associated with the format specifier.
|
||||
* word - beginning of the format specifier's word.
|
||||
* l - length of the format specifier's word.
|
||||
* out - output buffer where to store the result. Size: PATH_MAX.
|
||||
*
|
||||
* This is called if a format specifier with the format below was found:
|
||||
*
|
||||
* % { word }
|
||||
*
|
||||
* As a special edge case, an incomplete format at the end of the string
|
||||
* is processed as well:
|
||||
*
|
||||
* % { word \0
|
||||
*
|
||||
* Any valid format specified width is supported, e.g. "%12{host}".
|
||||
*
|
||||
* The following specifier keywords are currently supported:
|
||||
*
|
||||
* host Replaced with the name of the local machine (see gethostname(2)).
|
||||
* fps Equivalent to %fps.
|
||||
*/
|
||||
static void mystrftime_long (const struct ctx_cam *cam,
|
||||
int width, const char *word, int l, char *out)
|
||||
{
|
||||
#define SPECIFIERWORD(k) ((strlen(k)==l) && (!strncmp (k, word, l)))
|
||||
|
||||
if (SPECIFIERWORD("host")) {
|
||||
snprintf (out, PATH_MAX, "%*s", width, cam->hostname);
|
||||
return;
|
||||
}
|
||||
if (SPECIFIERWORD("fps")) {
|
||||
sprintf(out, "%*d", width, cam->movie_fps);
|
||||
return;
|
||||
}
|
||||
if (SPECIFIERWORD("dbeventid")) {
|
||||
sprintf(out, "%*llu", width, cam->database_event_id);
|
||||
return;
|
||||
}
|
||||
if (SPECIFIERWORD("ver")) {
|
||||
sprintf(out, "%*s", width, VERSION);
|
||||
return;
|
||||
}
|
||||
|
||||
// Not a valid modifier keyword. Log the error and ignore.
|
||||
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO,
|
||||
_("invalid format specifier keyword %*.*s"), l, l, word);
|
||||
|
||||
// Do not let the output buffer empty, or else where to restart the
|
||||
// interpretation of the user string will become dependent to far too
|
||||
// many conditions. Maybe change loop to "if (*pos_userformat == '%') {
|
||||
// ...} __else__ ..."?
|
||||
out[0] = '~'; out[1] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mystrftime
|
||||
*
|
||||
* Motion-specific variant of strftime(3) that supports additional format
|
||||
* specifiers in the format string.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* cam - current thread's context structure
|
||||
* s - destination string
|
||||
* max - max number of bytes to write
|
||||
* userformat - format string
|
||||
* tm - time information
|
||||
* filename - string containing full path of filename
|
||||
* set this to NULL if not relevant
|
||||
* sqltype - Filetype as used in SQL feature, set to 0 if not relevant
|
||||
*
|
||||
* Returns: number of bytes written to the string s
|
||||
*/
|
||||
size_t mystrftime(const struct ctx_cam *cam, char *s, size_t max, const char *userformat,
|
||||
const struct timespec *ts1, const char *filename, int sqltype)
|
||||
{
|
||||
char formatstring[PATH_MAX] = "";
|
||||
char tempstring[PATH_MAX] = "";
|
||||
char *format, *tempstr;
|
||||
const char *pos_userformat;
|
||||
int width;
|
||||
struct tm timestamp_tm;
|
||||
|
||||
localtime_r(&ts1->tv_sec, ×tamp_tm);
|
||||
|
||||
format = formatstring;
|
||||
|
||||
/* if mystrftime is called with userformat = NULL we return a zero length string */
|
||||
if (userformat == NULL) {
|
||||
*s = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (pos_userformat = userformat; *pos_userformat; ++pos_userformat) {
|
||||
|
||||
if (*pos_userformat == '%') {
|
||||
/*
|
||||
* Reset 'tempstr' to point to the beginning of 'tempstring',
|
||||
* otherwise we will eat up tempstring if there are many
|
||||
* format specifiers.
|
||||
*/
|
||||
tempstr = tempstring;
|
||||
tempstr[0] = '\0';
|
||||
width = 0;
|
||||
while ('0' <= pos_userformat[1] && pos_userformat[1] <= '9') {
|
||||
width *= 10;
|
||||
width += pos_userformat[1] - '0';
|
||||
++pos_userformat;
|
||||
}
|
||||
|
||||
switch (*++pos_userformat) {
|
||||
case '\0': // end of string
|
||||
--pos_userformat;
|
||||
break;
|
||||
|
||||
case 'v': // event
|
||||
sprintf(tempstr, "%0*d", width ? width : 2, cam->event_nr);
|
||||
break;
|
||||
|
||||
case 'q': // shots
|
||||
sprintf(tempstr, "%0*d", width ? width : 2,
|
||||
cam->current_image->shot);
|
||||
break;
|
||||
|
||||
case 'D': // diffs
|
||||
sprintf(tempstr, "%*d", width, cam->current_image->diffs);
|
||||
break;
|
||||
|
||||
case 'N': // noise
|
||||
sprintf(tempstr, "%*d", width, cam->noise);
|
||||
break;
|
||||
|
||||
case 'i': // motion width
|
||||
sprintf(tempstr, "%*d", width,
|
||||
cam->current_image->location.width);
|
||||
break;
|
||||
|
||||
case 'J': // motion height
|
||||
sprintf(tempstr, "%*d", width,
|
||||
cam->current_image->location.height);
|
||||
break;
|
||||
|
||||
case 'K': // motion center x
|
||||
sprintf(tempstr, "%*d", width, cam->current_image->location.x);
|
||||
break;
|
||||
|
||||
case 'L': // motion center y
|
||||
sprintf(tempstr, "%*d", width, cam->current_image->location.y);
|
||||
break;
|
||||
|
||||
case 'o': // threshold
|
||||
sprintf(tempstr, "%*d", width, cam->threshold);
|
||||
break;
|
||||
|
||||
case 'Q': // number of labels
|
||||
sprintf(tempstr, "%*d", width,
|
||||
cam->current_image->total_labels);
|
||||
break;
|
||||
|
||||
case 't': // camera id
|
||||
sprintf(tempstr, "%*d", width, cam->camera_id);
|
||||
break;
|
||||
|
||||
case 'C': // text_event
|
||||
if (cam->text_event_string[0])
|
||||
snprintf(tempstr, PATH_MAX, "%*s", width,
|
||||
cam->text_event_string);
|
||||
else
|
||||
++pos_userformat;
|
||||
break;
|
||||
|
||||
case 'w': // picture width
|
||||
sprintf(tempstr, "%*d", width, cam->imgs.width);
|
||||
break;
|
||||
|
||||
case 'h': // picture height
|
||||
sprintf(tempstr, "%*d", width, cam->imgs.height);
|
||||
break;
|
||||
|
||||
case 'f': // filename -- or %fps
|
||||
if ((*(pos_userformat+1) == 'p') && (*(pos_userformat+2) == 's')) {
|
||||
sprintf(tempstr, "%*d", width, cam->movie_fps);
|
||||
pos_userformat += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (filename)
|
||||
snprintf(tempstr, PATH_MAX, "%*s", width, filename);
|
||||
else
|
||||
++pos_userformat;
|
||||
break;
|
||||
|
||||
case 'n': // sqltype
|
||||
if (sqltype)
|
||||
sprintf(tempstr, "%*d", width, sqltype);
|
||||
else
|
||||
++pos_userformat;
|
||||
break;
|
||||
|
||||
case '{': // long format specifier word.
|
||||
{
|
||||
const char *word = ++pos_userformat;
|
||||
while ((*pos_userformat != '}') && (*pos_userformat != 0))
|
||||
++pos_userformat;
|
||||
mystrftime_long (cam, width, word, (int)(pos_userformat-word), tempstr);
|
||||
if (*pos_userformat == '\0') --pos_userformat;
|
||||
}
|
||||
break;
|
||||
|
||||
case '$': // thread name
|
||||
if (cam->conf.camera_name && cam->conf.camera_name[0])
|
||||
snprintf(tempstr, PATH_MAX, "%s", cam->conf.camera_name);
|
||||
else
|
||||
++pos_userformat;
|
||||
break;
|
||||
|
||||
default: // Any other code is copied with the %-sign
|
||||
*format++ = '%';
|
||||
*format++ = *pos_userformat;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a format specifier was found and used, copy the result from
|
||||
* 'tempstr' to 'format'.
|
||||
*/
|
||||
if (tempstr[0]) {
|
||||
while ((*format = *tempstr++) != '\0')
|
||||
++format;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* For any other character than % we just simply copy the character */
|
||||
*format++ = *pos_userformat;
|
||||
}
|
||||
|
||||
*format = '\0';
|
||||
format = formatstring;
|
||||
|
||||
return strftime(s, max, format, ×tamp_tm);
|
||||
}
|
||||
|
||||
void mythreadname_set(const char *abbr, int threadnbr, const char *threadname){
|
||||
/* When the abbreviation is sent in as null, that means we are being
|
||||
* provided a fully filled out thread name (usually obtained from a
|
||||
* previously called get_threadname so we set it without additional
|
||||
* formatting.
|
||||
*/
|
||||
|
||||
char tname[16];
|
||||
if (abbr != NULL){
|
||||
snprintf(tname, sizeof(tname), "%s%d%s%s",abbr,threadnbr,
|
||||
threadname ? ":" : "",
|
||||
threadname ? threadname : "");
|
||||
} else {
|
||||
snprintf(tname, sizeof(tname), "%s",threadname);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
pthread_setname_np(tname);
|
||||
#elif defined(BSD)
|
||||
pthread_set_name_np(pthread_self(), tname);
|
||||
#elif HAVE_PTHREAD_SETNAME_NP
|
||||
pthread_setname_np(pthread_self(), tname);
|
||||
#else
|
||||
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, _("Unable to set thread name %s"), tname);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void mythreadname_get(char *threadname){
|
||||
|
||||
#if ((!defined(BSD) && HAVE_PTHREAD_GETNAME_NP) || defined(__APPLE__))
|
||||
char currname[16];
|
||||
pthread_getname_np(pthread_self(), currname, sizeof(currname));
|
||||
snprintf(threadname, sizeof(currname), "%s",currname);
|
||||
#else
|
||||
snprintf(threadname, 8, "%s","Unknown");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int mycheck_passthrough(struct ctx_cam *cam){
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR < 55)
|
||||
if (cam->movie_passthrough)
|
||||
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("FFMPEG version too old. Disabling pass-through processing."));
|
||||
return 0;
|
||||
#else
|
||||
if (cam->movie_passthrough){
|
||||
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("pass-through is enabled but is still experimental."));
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void mytranslate_locale_chg(const char *langcd){
|
||||
#ifdef HAVE_GETTEXT
|
||||
/* This routine is for development testing only. It is not used for
|
||||
* regular users because once this locale is change, it changes the
|
||||
* whole computer over to the new locale. Therefore, we just return
|
||||
*/
|
||||
return;
|
||||
|
||||
setenv ("LANGUAGE", langcd, 1);
|
||||
/* Invoke external function to change locale*/
|
||||
++_nl_msg_cat_cntr;
|
||||
#else
|
||||
if (langcd != NULL) MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO,"No native language support");
|
||||
#endif
|
||||
}
|
||||
|
||||
void mytranslate_init(void){
|
||||
#ifdef HAVE_GETTEXT
|
||||
mytranslate_text("", 1);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
//translate_locale_chg("li");
|
||||
mytranslate_locale_chg("es");
|
||||
|
||||
bindtextdomain ("motion", LOCALEDIR);
|
||||
bind_textdomain_codeset ("motion", "UTF-8");
|
||||
textdomain ("motion");
|
||||
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO,_("Language: English"));
|
||||
|
||||
#else
|
||||
/* Disable native language support */
|
||||
mytranslate_text("", 0);
|
||||
|
||||
/* This avoids a unused function warning */
|
||||
translate_locale_chg("en");
|
||||
#endif
|
||||
}
|
||||
|
||||
char* mytranslate_text(const char *msgid, int setnls){
|
||||
static int nls_enabled = TRUE;
|
||||
|
||||
if (setnls == 0){
|
||||
if (nls_enabled){
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO,_("Disabling native language support"));
|
||||
}
|
||||
nls_enabled = FALSE;
|
||||
return NULL;
|
||||
|
||||
} else if (setnls == 1){
|
||||
if (!nls_enabled){
|
||||
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO,_("Enabling native language support"));
|
||||
}
|
||||
nls_enabled = TRUE;
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
#ifdef HAVE_GETTEXT
|
||||
if (nls_enabled){
|
||||
return (char*)gettext(msgid);
|
||||
} else {
|
||||
return (char*)msgid;
|
||||
}
|
||||
#else
|
||||
return (char*)msgid;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mystrcpy
|
||||
* Is used to assign string type fields (e.g. config options)
|
||||
* In a way so that we the memory is malloc'ed to fit the string.
|
||||
* If a field is already pointing to a string (not NULL) the memory of the
|
||||
* old string is free'd and new memory is malloc'ed and filled with the
|
||||
* new string is copied into the the memory and with the char pointer
|
||||
* pointing to the new string.
|
||||
*
|
||||
* from - pointer to the new string we want to copy
|
||||
* to - the pointer to the current string (or pointing to NULL)
|
||||
* If not NULL the memory it points to is free'd.
|
||||
*
|
||||
* Returns pointer to the new string which is in malloc'ed memory
|
||||
* FIXME The strings that are malloc'ed with this function should be freed
|
||||
* when the motion program is terminated normally instead of relying on the
|
||||
* OS to clean up.
|
||||
*/
|
||||
char *mystrcpy(char *to, const char *from){
|
||||
/*
|
||||
* Free the memory used by the to string, if such memory exists,
|
||||
* and return a pointer to a freshly malloc()'d string with the
|
||||
* same value as from.
|
||||
*/
|
||||
|
||||
if (to != NULL)
|
||||
free(to);
|
||||
|
||||
return mystrdup(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* mystrdup
|
||||
* Truncates the string to the length given by the environment
|
||||
* variable PATH_MAX to ensure that config options can always contain
|
||||
* a really long path but no more than that.
|
||||
*
|
||||
* Returns a pointer to a freshly malloc()'d string with the same
|
||||
* value as the string that the input parameter 'from' points to,
|
||||
* or NULL if the from string is 0 characters.
|
||||
*/
|
||||
char *mystrdup(const char *from)
|
||||
{
|
||||
char *tmp;
|
||||
size_t stringlength;
|
||||
|
||||
if (from == NULL || !strlen(from)) {
|
||||
tmp = NULL;
|
||||
} else {
|
||||
stringlength = strlen(from);
|
||||
stringlength = (stringlength < PATH_MAX ? stringlength : PATH_MAX);
|
||||
tmp = (char*)mymalloc(stringlength + 1);
|
||||
strncpy(tmp, from, stringlength);
|
||||
|
||||
/*
|
||||
* We must ensure the string always has a NULL terminator.
|
||||
* This necessary because strncpy will not append a NULL terminator
|
||||
* if the original string is greater than string length.
|
||||
*/
|
||||
tmp += stringlength;
|
||||
*tmp = '\0';
|
||||
tmp -= stringlength;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* The section below is the "my" section of functions.
|
||||
* These are designed to be extremely simple version specific
|
||||
* variants of the libav functions.
|
||||
****************************************************************************/
|
||||
|
||||
/*********************************************/
|
||||
AVFrame *myframe_alloc(void){
|
||||
AVFrame *pic;
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 55)
|
||||
pic = av_frame_alloc();
|
||||
#else
|
||||
pic = avcodec_alloc_frame();
|
||||
#endif
|
||||
return pic;
|
||||
}
|
||||
/*********************************************/
|
||||
void myframe_free(AVFrame *frame){
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 55)
|
||||
av_frame_free(&frame);
|
||||
#else
|
||||
av_freep(&frame);
|
||||
#endif
|
||||
}
|
||||
/*********************************************/
|
||||
int myimage_get_buffer_size(enum MyPixelFormat pix_fmt, int width, int height){
|
||||
int retcd = 0;
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 57)
|
||||
int align = 1;
|
||||
retcd = av_image_get_buffer_size(pix_fmt, width, height, align);
|
||||
#else
|
||||
retcd = avpicture_get_size(pix_fmt, width, height);
|
||||
#endif
|
||||
return retcd;
|
||||
}
|
||||
/*********************************************/
|
||||
int myimage_copy_to_buffer(AVFrame *frame, uint8_t *buffer_ptr, enum MyPixelFormat pix_fmt,int width, int height,int dest_size){
|
||||
int retcd = 0;
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 57)
|
||||
int align = 1;
|
||||
retcd = av_image_copy_to_buffer((uint8_t *)buffer_ptr,dest_size
|
||||
,(const uint8_t * const*)frame,frame->linesize,pix_fmt,width,height,align);
|
||||
#else
|
||||
retcd = avpicture_layout((const AVPicture*)frame,pix_fmt,width,height
|
||||
,(unsigned char *)buffer_ptr,dest_size);
|
||||
#endif
|
||||
return retcd;
|
||||
}
|
||||
/*********************************************/
|
||||
int myimage_fill_arrays(AVFrame *frame,uint8_t *buffer_ptr,enum MyPixelFormat pix_fmt,int width,int height){
|
||||
int retcd = 0;
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 57)
|
||||
int align = 1;
|
||||
retcd = av_image_fill_arrays(
|
||||
frame->data
|
||||
,frame->linesize
|
||||
,buffer_ptr
|
||||
,pix_fmt
|
||||
,width
|
||||
,height
|
||||
,align
|
||||
);
|
||||
#else
|
||||
retcd = avpicture_fill(
|
||||
(AVPicture *)frame
|
||||
,buffer_ptr
|
||||
,pix_fmt
|
||||
,width
|
||||
,height);
|
||||
#endif
|
||||
return retcd;
|
||||
}
|
||||
/*********************************************/
|
||||
void mypacket_unref(AVPacket pkt){
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 57)
|
||||
av_packet_unref(&pkt);
|
||||
#else
|
||||
av_free_packet(&pkt);
|
||||
#endif
|
||||
}
|
||||
/*********************************************/
|
||||
void myavcodec_close(AVCodecContext *codec_context){
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (LIBAVFORMAT_VERSION_MINOR >= 41))
|
||||
avcodec_free_context(&codec_context);
|
||||
#else
|
||||
avcodec_close(codec_context);
|
||||
#endif
|
||||
}
|
||||
/*********************************************/
|
||||
int mycopy_packet(AVPacket *dest_pkt, AVPacket *src_pkt){
|
||||
#if (LIBAVFORMAT_VERSION_MAJOR >= 55)
|
||||
return av_packet_ref(dest_pkt, src_pkt);
|
||||
#else
|
||||
/* Old versions of libav do not support copying packet
|
||||
* We therefore disable the pass through recording and
|
||||
* for this function, simply do not do anything
|
||||
*/
|
||||
if (dest_pkt == src_pkt ){
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*********************************************/
|
||||
Reference in New Issue
Block a user