Added support for libav V53

This commit is contained in:
Dave
2014-06-19 20:17:20 -06:00
parent 87d271e914
commit ca413db53c
7 changed files with 166 additions and 285 deletions

12
CHANGELOG Normal file → Executable file
View File

@@ -60,9 +60,15 @@ Features
* Revised INSTALL with samples(Mr-Dave)
* Revisions for RTSP and code standard.(Mr-Dave)
* Plugged most(?) memory leaks in RTSP. (Mr-Dave)
* Undo changes caused by code editor and other unnecessary changes
* Moved call to netcam_shutdown_rtsp into netcam_cleanup where it belongs.
* Regession fix for memory leaks and reconnection
* Undo changes caused by code editor and other unnecessary changes (Mr-Dave)
* Moved call to netcam_shutdown_rtsp into netcam_cleanup where it belongs. (Mr-Dave)
* Regession fix for memory leaks and reconnection (Mr-Dave)
* Eliminated requirement to manually build FFMPEG for RTSP support. (Mr-Dave)
* Revised RTSP to support version 53 of libavformat (Mr-Dave)
* Revised FFMPEG.c to eliminate warnings and functions no longer supported by Libav/FFMPEG(Mr-Dave)
* Revised INSTALL to have sample PI configure option.(Mr-Dave)
* Revised configure.ac to generate compiler flag AVFMT_V53.(Mr-Dave)
* Revised INSTALL to indicate standard APT packages for RTSP (Mr-Dave)
Bugfixes

72
INSTALL Normal file → Executable file
View File

@@ -1,36 +1,36 @@
Required Packages:
sudo apt-get install autoconf automake build-essential libjpeg-turbo8-dev libzip-dev
Obtain source code (via git)
sudo apt-get install git
cd ~
git clone {https://github.com/your favorite fork}
To rebuild the motion configure file use
autoreconf
Optional: With FFMPEG support:
Build FFMPEG via their instructions
Change to location of the motion source code
cd ~/motion
Configure with manually built ffmpeg which installs to ~/bin and ~/ffmpeg_build
Basic
./configure --with-ffmpeg=$HOME/ffmpeg_build --with-ffmpeg-headers=$HOME/ffmpeg_build/include
With extra libraries for ffmpeg IMPORTANT NOTE: Your libraries will vary depending upon your build of FFMPEG
./configure --with-ffmpeg=$HOME/ffmpeg_build --with-ffmpeg-headers=$HOME/ffmpeg_build/include --with-ffmpeg-libs=" -lavformat -lswscale -lavcodec -lavutil -lfdk-aac -lswresample -lm -lopus -lz -lva -lvpx -lx264 -lmp3lame -lbz2 -ldl -lvorbisenc -lvorbis -ltheoraenc -ltheoradec "
With extra libraries for ffmpeg and install to ~/motion_build
./configure --prefix=$HOME/motion_build --with-ffmpeg=$HOME/ffmpeg_build --with-ffmpeg-headers=$HOME/ffmpeg_build/include --with-ffmpeg-libs=" -lavformat -lswscale -lavcodec -lavutil -lfdk-aac -lswresample -lm -lopus -lz -lva -lvpx -lx264 -lmp3lame -lbz2 -ldl -lvorbisenc -lvorbis -ltheoraenc -ltheoradec "
With APT versions of ffmpeg libraries
sudo apt-get install libavformat-dev libavcodec-dev
Without any FFMPEG support or just any installed version of FFMPEG
./configure
Once configured type:
make
make install
Required Packages:
sudo apt-get install autoconf automake build-essential libtool libjpeg8-dev libzip-dev
Obtain source code (via git)
sudo apt-get install git
cd ~
git clone {https://github.com/your favorite fork}
To rebuild the motion configure file use
autoreconf
Optional: With FFMPEG support:
Build FFMPEG via their instructions
Configure with manually built ffmpeg which currently installs to ~/bin and ~/ffmpeg_build
Basic
./configure --with-ffmpeg=$HOME/ffmpeg_build --with-ffmpeg-headers=$HOME/ffmpeg_build/include
With extra libraries for ffmpeg IMPORTANT NOTE: Your libraries will vary depending upon your build of FFMPEG
./configure --with-ffmpeg=$HOME/ffmpeg_build --with-ffmpeg-headers=$HOME/ffmpeg_build/include --with-ffmpeg-libs=" -lavformat -lswscale -lavcodec -lavutil -lfdk-aac -lswresample -lm -lopus -lz -lva -lvpx -lx264 -lmp3lame -lbz2 -ldl -lvorbisenc -lvorbis -ltheoraenc -ltheoradec "
With extra libraries for ffmpeg and install to ~/motion_build
./configure --prefix=$HOME/motion_build --with-ffmpeg=$HOME/ffmpeg_build --with-ffmpeg-headers=$HOME/ffmpeg_build/include --with-ffmpeg-libs=" -lavformat -lswscale -lavcodec -lavutil -lfdk-aac -lswresample -lm -lopus -lz -lva -lvpx -lx264 -lmp3lame -lbz2 -ldl -lvorbisenc -lvorbis -ltheoraenc -ltheoradec "
With LIBAV APT versions of libraries
sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev libav-tools
Without any LIBAV/FFMPEG support or the installed version of libavcodec/libavformat
./configure
Sample PI configuration with LIBAV
./configure --with-ffmpeg=/usr/lib/arm-linux-gnueabihf --with-ffmpeg-headers=/usr/include
Once configured type:
make
make install

34
configure.ac Normal file → Executable file
View File

@@ -441,6 +441,11 @@ else if test "${FFMPEG_DIR}" = "yes"; then
FFMPEG_OK="found"
FFMPEG_LIB="/usr/lib/x86_64-linux-gnu"
FFMPEG_DIR="/usr"
elif test -f /usr/lib/i386-linux-gnu/libavcodec.a -o -f /usr/lib/i386-linux-gnu/libavcodec.so && test /usr/lib/i386-linux-gnu/libavformat.a -o -f /usr/lib/i386-linux-gnu/libavformat.so ; then
AC_MSG_RESULT(found in /usr/lib/i386-linux-gnu)
FFMPEG_OK="found"
FFMPEG_LIB="/usr/lib/i386-linux-gnu"
FFMPEG_DIR="/usr"
else
AC_MSG_RESULT(not found)
echo ""
@@ -551,7 +556,7 @@ if test "${FFMPEG_OK}" = "found"; then
FFMPEG_OBJ="ffmpeg.o"
AC_SUBST(FFMPEG_OBJ)
AC_MSG_CHECKING(avformat)
AC_MSG_CHECKING(avformat version 55)
AC_RUN_IFELSE([AC_LANG_SOURCE([
[
#include <${AVFORMAT_DIR}>
@@ -560,15 +565,38 @@ if test "${FFMPEG_OK}" = "found"; then
return 0;
}
]])],
[AC_MSG_RESULT(version previous to 55)],
[
AC_MSG_RESULT(no)
AC_MSG_CHECKING(avformat version 53)
AC_RUN_IFELSE([AC_LANG_SOURCE([
[
AC_MSG_RESULT(version 55 or higher)
#include <${AVFORMAT_DIR}>
int main(void){
if (LIBAVFORMAT_VERSION_MAJOR = 53) return -1;
return 0;
}
]])],
[AC_MSG_RESULT(no)],
[
AC_MSG_RESULT(yes)
TEMP_CFLAGS="${TEMP_CFLAGS} -DAVFMT_V53"
RTPS_OBJ="netcam_rtsp.o"
AC_SUBST(RTPS_OBJ)
]
)
],
[
AC_MSG_RESULT( yes version 55 or higher)
TEMP_CFLAGS="${TEMP_CFLAGS} -DFFMPEG_V55"
RTPS_OBJ="netcam_rtsp.o"
AC_SUBST(RTPS_OBJ)
]
)
AC_MSG_CHECKING([file_protocol is defined in ffmpeg ?])
saved_CFLAGS=$CFLAGS
saved_LIBS=$LIBS

197
ffmpeg.c Normal file → Executable file
View File

@@ -14,7 +14,7 @@
#include "ffmpeg.h"
#include "motion.h"
#if LIBAVCODEC_BUILD > 4680
/*
* FFmpeg after build 4680 doesn't have support for mpeg1 videos with
@@ -150,89 +150,37 @@ URLProtocol mpeg1_file_protocol = {
#include "avstring.h"
#endif
/**
* file_open
*
*/
static int file_open(URLContext *h, const char *filename, int flags)
{
const char *mode;
FILE *fh;
size_t bufsize = 0;
av_strstart(filename, "file:", &filename);
if (flags & URL_RDWR) {
mode = "wb+";
bufsize = BUFSIZE_1MEG;
} else if (flags & URL_WRONLY) {
mode = "wb";
bufsize = BUFSIZE_1MEG;
} else {
mode = "rb";
}
fh = myfopen(filename, mode, bufsize);
if (fh == NULL)
return AVERROR(ENOENT);
h->priv_data = (void *)fh;
return 0;
}
/**
* file_read
*/
static int file_read(URLContext *h, unsigned char *buf, int size)
{
FILE *fh = (FILE *)h->priv_data;
return fread(buf, 1, size, fh);
}
/**
* file_write
*/
static int file_write(URLContext *h, unsigned char *buf, int size)
{
FILE *fh = (FILE *)h->priv_data;
return fwrite(buf, 1, size, fh);
}
/**
* file_seek
*/
static int64_t file_seek(URLContext *h, int64_t pos, int whence)
{
FILE *fh = (FILE *)h->priv_data;
if (fseek(fh, pos, whence))
return -1;
return ftell(fh);
}
/**
* file_close
*/
static int file_close(URLContext *h)
{
FILE *fh = (FILE *)h->priv_data;
return myfclose(fh);
}
URLProtocol file_protocol = {
"file",
file_open,
file_read,
file_write,
file_seek,
file_close,
#if LIBAVFORMAT_BUILD >= (52<<16 | 31<<8)
NULL,
NULL,
NULL,
#endif
};
#endif // HAVE_FFMPEG_NEW
#endif // FF_API_NEW_AVIO
/****************************************************************************
* The section below is the "my" section of functions.
* These are designed to be extremely simple version specific
* variants of the libav functions.
****************************************************************************/
AVFrame *my_frame_alloc(void){
AVFrame *pic;
#ifdef FFMPEG_V55
pic = av_frame_alloc();
#else
pic = avcodec_alloc_frame();
#endif
return pic;
}
void my_frame_free(AVFrame *frame){
#ifdef FFMPEG_V55
av_frame_free(&frame);
#else
//avcodec_free_frame(&frame);
//av_frame_free(&netcam->rtsp->frame);
av_freep(&frame);
#endif
}
/****************************************************************************
****************************************************************************
****************************************************************************/
/**
* mpeg1_write_trailer
@@ -244,16 +192,8 @@ URLProtocol file_protocol = {
*/
static int mpeg1_write_trailer(AVFormatContext *s)
{
#if defined FF_API_NEW_AVIO
avio_write(s->pb, mpeg1_trailer, 4);
avio_flush(s->pb);
#elif LIBAVFORMAT_BUILD >= (52<<16)
put_buffer(s->pb, mpeg1_trailer, 4);
put_flush_packet(s->pb);
#else
put_buffer(&s->pb, mpeg1_trailer, 4);
put_flush_packet(&s->pb);
#endif /* FF_API_NEW_AVIO -- LIBAVFORMAT_BUILD >= (52<<16) */
return 0; /* success */
}
@@ -277,26 +217,6 @@ void ffmpeg_init()
av_log_set_level(AV_LOG_ERROR);
#endif
#if defined FF_API_NEW_AVIO
#else
/*
* Copy the functions to use for the append file protocol from the standard
* file protocol.
*/
mpeg1_file_protocol.url_read = file_protocol.url_read;
mpeg1_file_protocol.url_write = file_protocol.url_write;
mpeg1_file_protocol.url_seek = file_protocol.url_seek;
mpeg1_file_protocol.url_close = file_protocol.url_close;
/* Register the append file protocol. */
#ifdef FFMPEG_V55
av_register_protocol2(&mpeg1_file_protocol, sizeof(mpeg1_file_protocol));
#else
av_register_protocol(&mpeg1_file_protocol);
#endif
#endif // FF_API_NEW_AVIO
}
/**
@@ -458,7 +378,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
snprintf(ffmpeg->codec, sizeof(ffmpeg->codec), "%s", ffmpeg_video_codec);
/* Allocation the output media context. */
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
ffmpeg->oc = avformat_alloc_context();
#else
ffmpeg->oc = av_alloc_format_context();
@@ -483,11 +403,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
/* Create a new video stream and initialize the codecs. */
ffmpeg->video_st = NULL;
if (ffmpeg->oc->oformat->video_codec != CODEC_ID_NONE) {
#if defined FF_API_NEW_AVIO
ffmpeg->video_st = avformat_new_stream(ffmpeg->oc, NULL /* Codec */);
#else
ffmpeg->video_st = av_new_stream(ffmpeg->oc, 0);
#endif
if (!ffmpeg->video_st) {
MOTION_LOG(ERR, TYPE_ENCODER, SHOW_ERRNO, "%s: av_new_stream - could"
" not alloc stream");
@@ -549,18 +465,6 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
#if defined FF_API_NEW_AVIO
// pass the options to avformat_write_header directly
#else
/* Set the output parameters (must be done even if no parameters). */
if (av_set_parameters(ffmpeg->oc, NULL) < 0) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: av_set_parameters error:"
" Invalid output format parameters");
ffmpeg_cleanups(ffmpeg);
return NULL;
}
#endif
/* Dump the format settings. This shows how the various streams relate to each other. */
//dump_format(ffmpeg->oc, 0, filename, 1);
@@ -584,11 +488,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
pthread_mutex_lock(&global_lock);
/* Open the codec */
#if defined FF_API_NEW_AVIO
ret = avcodec_open2(c, codec, NULL /* options */ );
#else
ret = avcodec_open(c, codec);
#endif
if (ret < 0) {
/* Release the lock. */
@@ -615,11 +515,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
}
/* Allocate the encoded raw picture. */
#ifdef FFMPEG_V55
ffmpeg->picture = av_frame_alloc();
#else
ffmpeg->picture = avcodec_alloc_frame();
#endif
ffmpeg->picture = my_frame_alloc();
if (!ffmpeg->picture) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, "%s: avcodec_alloc_frame -"
@@ -659,11 +555,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
snprintf(file_proto, sizeof(file_proto), "%s", filename);
#if defined FF_API_NEW_AVIO
if (avio_open(&ffmpeg->oc->pb, file_proto, URL_WRONLY) < 0) {
#else
if (url_fopen(&ffmpeg->oc->pb, file_proto, URL_WRONLY) < 0) {
#endif
/* Path did not exist? */
if (errno == ENOENT) {
/* Create path for file (don't use file_proto)... */
@@ -672,12 +564,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
return NULL;
}
#if defined FF_API_NEW_AVIO
if (avio_open(&ffmpeg->oc->pb, file_proto, URL_WRONLY) < 0) {
#else
/* And retry opening the file (use file_proto). */
if (url_fopen(&ffmpeg->oc->pb, file_proto, URL_WRONLY) < 0) {
#endif
MOTION_LOG(ERR, TYPE_ENCODER, SHOW_ERRNO, "%s: url_fopen -"
" error opening file %s", filename);
ffmpeg_cleanups(ffmpeg);
@@ -701,11 +588,7 @@ struct ffmpeg *ffmpeg_open(char *ffmpeg_video_codec, char *filename,
}
/* Write the stream header, if any. */
#if defined FF_API_NEW_AVIO
avformat_write_header(ffmpeg->oc, NULL);
#else
av_write_header(ffmpeg->oc);
#endif // FF_API_NEW_AVIO
return ffmpeg;
}
@@ -773,13 +656,7 @@ void ffmpeg_close(struct ffmpeg *ffmpeg)
if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) {
/* Close the output file. */
#if defined FF_API_NEW_AVIO
avio_close(ffmpeg->oc->pb);
#elif LIBAVFORMAT_BUILD >= (52<<16)
url_fclose(ffmpeg->oc->pb);
#else
url_fclose(&ffmpeg->oc->pb);
#endif /* FF_API_NEW_AVIO -- LIBAVFORMAT_BUILD >= (52<<16) */
}
@@ -840,7 +717,7 @@ int ffmpeg_put_other_image(struct ffmpeg *ffmpeg, unsigned char *y,
*/
int ffmpeg_put_frame(struct ffmpeg *ffmpeg, AVFrame *pic)
{
int out_size, ret, got_packet_ptr;
int out_size, ret;
#ifdef FFMPEG_AVWRITEFRAME_NEWAPI
AVPacket pkt;
@@ -867,6 +744,8 @@ int ffmpeg_put_frame(struct ffmpeg *ffmpeg, AVFrame *pic)
} else {
/* Encodes the image. */
#if defined FF_API_NEW_AVIO
int got_packet_ptr;
pkt.data = ffmpeg->video_outbuf;
pkt.size = ffmpeg->video_outbuf_size;
@@ -936,11 +815,7 @@ AVFrame *ffmpeg_prepare_frame(struct ffmpeg *ffmpeg, unsigned char *y,
{
AVFrame *picture;
#ifdef FFMPEG_V55
picture = av_frame_alloc();
#else
picture = avcodec_alloc_frame();
#endif
picture = my_frame_alloc();
if (!picture) {
MOTION_LOG(ERR, TYPE_ENCODER, SHOW_ERRNO, "%s: Could not alloc frame");
@@ -989,7 +864,7 @@ void ffmpeg_deinterlace(unsigned char *img, int width, int height)
picture.linesize[2] = width2;
/* We assume using 'PIX_FMT_YUV420P' always */
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
MOTION_LOG(ALR, TYPE_NETCAM, NO_ERRNO, "%s: Deinterlace depreciated for recent versions of FFMPEG.");
#else
avpicture_deinterlace(&picture, &picture, PIX_FMT_YUV420P, width, height);

3
ffmpeg.h Normal file → Executable file
View File

@@ -95,4 +95,7 @@ void ffmpeg_deinterlace(unsigned char *, int, int);
/* Setup an avcodec log handler. */
void ffmpeg_avcodec_log(void *, int, const char *, va_list);
AVFrame *my_frame_alloc(void);
void my_frame_free(AVFrame *frame);
#endif /* _INCLUDE_FFMPEG_H_ */

21
netcam.c Normal file → Executable file
View File

@@ -45,7 +45,7 @@
#include <sys/socket.h>
#include "netcam_ftp.h"
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
#include "netcam_rtsp.h"
#endif
@@ -149,7 +149,7 @@ static void netcam_url_parse(struct url_t *parse_url, const char *text_url)
{
char *s;
int i;
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
const char *re = "(http|ftp|mjpg|rtsp)://(((.*):(.*))@)?"
"([^/:]|[-.a-z0-9]+)(:([0-9]+))?($|(/[^:]*))";
#else
@@ -211,7 +211,7 @@ static void netcam_url_parse(struct url_t *parse_url, const char *text_url)
parse_url->port = 80;
else if (!strcmp(parse_url->service, "ftp"))
parse_url->port = 21;
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
else if (!strcmp(parse_url->service, "rtsp") && parse_url->port == 0)
parse_url->port = 554;
#endif
@@ -2018,7 +2018,7 @@ static void *netcam_handler_loop(void *arg)
}
}
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
if (netcam->caps.streaming == NCS_RTSP) {
if (netcam->rtsp->format_context == NULL) { // We must have disconnected. Try to reconnect
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Attempting to reconnect");
@@ -2433,7 +2433,7 @@ static int netcam_setup_ftp(netcam_context_ptr netcam, struct url_t *url)
return 0;
}
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
static int netcam_setup_rtsp(netcam_context_ptr netcam, struct url_t *url)
{
struct context *cnt = netcam->cnt;
@@ -2518,7 +2518,6 @@ static int netcam_setup_rtsp(netcam_context_ptr netcam, struct url_t *url)
*/
ret = rtsp_connect(netcam);
if (ret < 0){
netcam_shutdown_rtsp(netcam);
return ret;
}
@@ -2708,8 +2707,8 @@ void netcam_cleanup(netcam_context_ptr netcam, int init_retry_flag)
if (netcam->response != NULL)
free(netcam->response);
#ifdef FFMPEG_V55
if (netcam->caps.streaming == NCS_RTSP)
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
if ((netcam->caps.streaming == NCS_RTSP) && (netcam->rtsp->connected == 1))
netcam_shutdown_rtsp(netcam);
#endif
@@ -2945,7 +2944,7 @@ int netcam_start(struct context *cnt)
strcpy(url.service, "http"); /* Put back a real URL service. */
retval = netcam_setup_mjpg(netcam, &url);
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
} else if ((url.service) && (!strcmp(url.service, "rtsp"))) {
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, "%s: now calling"
" netcam_setup_rtsp()");
@@ -2975,7 +2974,7 @@ int netcam_start(struct context *cnt)
return -1;
}
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
if (netcam->caps.streaming != NCS_RTSP) {
#endif
/*
@@ -3008,7 +3007,7 @@ int netcam_start(struct context *cnt)
" is not modulo 8", netcam->height);
return -3;
}
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
} else {
// not jpeg, get the dimensions
netcam->width = netcam->rtsp->codec_context->width;

112
netcam_rtsp.c Normal file → Executable file
View File

@@ -2,11 +2,9 @@
#include "netcam_rtsp.h"
#include "motion.h"
#ifdef FFMPEG_V55
#if ((defined FFMPEG_V55) || (defined AVFMT_V53))
/* Only recent versions of FFMPEG are supported since
* no documentation on how to code the old versions exist
*/
#include "ffmpeg.h"
/****************************************************
* Duplicated static functions - FIXME
@@ -58,8 +56,10 @@ static void netcam_check_buffsize(netcam_buff_ptr buff, size_t numbytes)
static int decode_packet(AVPacket *packet, netcam_buff_ptr buffer, AVFrame *frame, AVCodecContext *cc)
{
int check = 0;
int ret = avcodec_decode_video2(cc, frame, &check, packet);
int frame_size = 0;
int ret = 0;
ret = avcodec_decode_video2(cc, frame, &check, packet);
if (ret < 0) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Error decoding video packet");
return 0;
@@ -70,14 +70,12 @@ static int decode_packet(AVPacket *packet, netcam_buff_ptr buffer, AVFrame *fram
return 0;
}
int frame_size = av_image_get_buffer_size(cc->pix_fmt, cc->width, cc->height, 1);
/* Assure there's enough room in the buffer. */
frame_size = avpicture_get_size(cc->pix_fmt, cc->width, cc->height);
netcam_check_buffsize(buffer, frame_size);
av_image_copy_to_buffer((uint8_t *)buffer->ptr, frame_size,
(const uint8_t **)(frame->data), frame->linesize,
cc->pix_fmt, cc->width, cc->height, 1);
avpicture_layout((const AVPicture*)frame,cc->pix_fmt,cc->width,cc->height
,(unsigned char *)buffer->ptr,frame_size );
buffer->used = frame_size;
@@ -92,7 +90,7 @@ static int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AV
AVCodec *dec = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if (ret < 0) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Could not find stream %s in input!", av_get_media_type_string(type));
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Could not find stream %s in input!", type);
return ret;
} else {
*stream_idx = ret;
@@ -101,11 +99,11 @@ static int open_codec_context(int *stream_idx, AVFormatContext *fmt_ctx, enum AV
dec_ctx = st->codec;
dec = avcodec_find_decoder(dec_ctx->codec_id);
if (!dec) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Failed to find %s codec!", av_get_media_type_string(type));
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Failed to find %s codec!", type);
return ret;
}
if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Failed to open %s codec!", av_get_media_type_string(type));
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, "%s: Failed to open %s codec!", type);
return ret;
}
}
@@ -136,7 +134,7 @@ struct rtsp_context *rtsp_new_context(void)
return ret;
}
static int decode_interrupt_cb(void *ctx)
static int interrupt_cb(void *ctx)
{
struct rtsp_context *rtsp = (struct rtsp_context *)ctx;
@@ -158,33 +156,34 @@ static int decode_interrupt_cb(void *ctx)
//should not be possible to get here
return 0;
}
int rtsp_connect(netcam_context_ptr netcam)
{
int ret;
int ret;
char errstr[128];
netcam->rtsp->connected = 0;
if (netcam->rtsp->path == NULL) {
MOTION_LOG(ALR, TYPE_NETCAM, NO_ERRNO, "%s: Null path passed to connect (%s)", netcam->rtsp->path);
return -1;
}
// open the network connection
AVDictionary *opts = 0;
av_dict_set(&opts, "rtsp_transport", "tcp", 0);
netcam->rtsp->format_context = avformat_alloc_context();
netcam->rtsp->format_context->interrupt_callback.callback = decode_interrupt_cb;
netcam->rtsp->format_context->interrupt_callback.callback = interrupt_cb;
netcam->rtsp->format_context->interrupt_callback.opaque = netcam->rtsp;
ret = avformat_open_input(&netcam->rtsp->format_context, netcam->rtsp->path, NULL, &opts);
if (ret < 0) {
MOTION_LOG(ALR, TYPE_NETCAM, NO_ERRNO, "%s: unable to open input(%s): %d - %s", netcam->rtsp->path,av_err2str(ret));
av_strerror(ret, errstr, sizeof(errstr));
MOTION_LOG(ALR, TYPE_NETCAM, NO_ERRNO, "%s: unable to open input(%s): %s", netcam->rtsp->path,errstr);
if (ret == -1094995529) MOTION_LOG(ALR, TYPE_NETCAM, NO_ERRNO, "%s: Authentication?");
av_dict_free(&opts);
avformat_close_input(&netcam->rtsp->format_context);
//The format context gets freed upon any error from open_input.
return ret;
}
av_dict_free(&opts);
@@ -207,10 +206,12 @@ int rtsp_connect(netcam_context_ptr netcam)
netcam->rtsp->codec_context = netcam->rtsp->format_context->streams[netcam->rtsp->video_stream_index]->codec;
netcam->rtsp->frame = av_frame_alloc();
netcam->rtsp->frame = my_frame_alloc();
// start up the feed
av_read_play(netcam->rtsp->format_context);
netcam->rtsp->connected = 1;
return 0;
}
@@ -218,10 +219,6 @@ int rtsp_connect(netcam_context_ptr netcam)
int netcam_read_rtsp_image(netcam_context_ptr netcam)
{
/* This code is called many times so optimize and do
* little as possible in here.
*/
struct timeval curtime;
netcam_buff_ptr buffer;
AVPacket packet;
@@ -233,7 +230,6 @@ int netcam_read_rtsp_image(netcam_context_ptr netcam)
buffer->used = 0;
av_init_packet(&packet);
packet.data = NULL;
packet.size = 0;
@@ -264,12 +260,12 @@ int netcam_read_rtsp_image(netcam_context_ptr netcam)
}
netcam->rtsp->readingframe = 0;
// at this point, we are finished with the packet and frame, so free them.
// at this point, we are finished with the packet
av_free_packet(&packet);
if (size_decoded == 0) {
// something went wrong, end of stream? Interupted?
MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "%s: invalid frame! %d", size_decoded);
MOTION_LOG(ERR, TYPE_NETCAM, SHOW_ERRNO, "%s: invalid frame! %d ", size_decoded);
av_free(netcam->rtsp->frame);
avcodec_close(netcam->rtsp->codec_context);
avformat_close_input(&netcam->rtsp->format_context);
@@ -284,57 +280,31 @@ int netcam_read_rtsp_image(netcam_context_ptr netcam)
}
netcam->receiving->image_time = curtime;
/*
* Calculate our "running average" time for this netcam's
* frame transmissions (except for the first time).
* Note that the average frame time is held in microseconds.
*/
if (netcam->last_image.tv_sec) {
netcam->av_frame_time = ((9.0 * netcam->av_frame_time) + 1000000.0 *
(curtime.tv_sec - netcam->last_image.tv_sec) +
(curtime.tv_usec- netcam->last_image.tv_usec)) / 10.0;
MOTION_LOG(DBG, TYPE_NETCAM, NO_ERRNO, "%s: Calculated frame time %f",
netcam->av_frame_time);
}
netcam->last_image = curtime;
netcam_buff *xchg;
/*
* read is complete - set the current 'receiving' buffer atomically
* as 'latest', and make the buffer previously in 'latest' become
* the new 'receiving'.
* the new 'receiving' and signal pic_ready.
*/
netcam->receiving->image_time = curtime;
netcam->last_image = curtime;
netcam_buff *xchg;
pthread_mutex_lock(&netcam->mutex);
xchg = netcam->latest;
netcam->latest = netcam->receiving;
netcam->receiving = xchg;
netcam->imgcnt++;
/*
* We have a new frame ready. We send a signal so that
* any thread (e.g. the motion main loop) waiting for the
* next frame to become available may proceed.
*/
pthread_cond_signal(&netcam->pic_ready);
xchg = netcam->latest;
netcam->latest = netcam->receiving;
netcam->receiving = xchg;
netcam->imgcnt++;
pthread_cond_signal(&netcam->pic_ready);
pthread_mutex_unlock(&netcam->mutex);
return 0;
}
void netcam_shutdown_rtsp(netcam_context_ptr netcam)
{
MOTION_LOG(ALR, TYPE_NETCAM, NO_ERRNO,"%s: shutting down rtsp");
av_free(netcam->rtsp->frame);
my_frame_free(netcam->rtsp->frame);
avcodec_close(netcam->rtsp->codec_context);
avformat_close_input(&netcam->rtsp->format_context);