"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "ffmpeg.c" between
motion-release-4.2.2.tar.gz and motion-Release-4.3.0.tar.gz

About: Motion monitors the video signal from one or more cameras and is able to detect motion.

ffmpeg.c  (motion-release-4.2.2):ffmpeg.c  (motion-Release-4.3.0)
skipping to change at line 186 skipping to change at line 186
} else { } else {
return 0; return 0;
} }
#endif #endif
} }
/*********************************************/ /*********************************************/
/**************************************************************************** /****************************************************************************
**************************************************************************** ****************************************************************************
****************************************************************************/ ****************************************************************************/
/*********************************************/
static void ffmpeg_free_nal(struct ffmpeg *ffmpeg){
if (ffmpeg->nal_info) {
free(ffmpeg->nal_info);
ffmpeg->nal_info = NULL;
ffmpeg->nal_info_len = 0;
}
}
static int ffmpeg_encode_nal(struct ffmpeg *ffmpeg){
// h264_v4l2m2m has NAL units separated from the first frame, which makes
// some players very unhappy.
if ((ffmpeg->pkt.pts == 0) && (!(ffmpeg->pkt.flags & AV_PKT_FLAG_KEY))) {
ffmpeg_free_nal(ffmpeg);
ffmpeg->nal_info_len = ffmpeg->pkt.size;
ffmpeg->nal_info = malloc(ffmpeg->nal_info_len);
if (ffmpeg->nal_info) {
memcpy(ffmpeg->nal_info, &ffmpeg->pkt.data[0], ffmpeg->nal_info_len)
;
return 1;
} else
ffmpeg->nal_info_len = 0;
} else if (ffmpeg->nal_info) {
int old_size = ffmpeg->pkt.size;
av_grow_packet(&ffmpeg->pkt, ffmpeg->nal_info_len);
memmove(&ffmpeg->pkt.data[ffmpeg->nal_info_len], &ffmpeg->pkt.data[0], o
ld_size);
memcpy(&ffmpeg->pkt.data[0], ffmpeg->nal_info, ffmpeg->nal_info_len);
ffmpeg_free_nal(ffmpeg);
}
return 0;
}
static int ffmpeg_timelapse_exists(const char *fname){ static int ffmpeg_timelapse_exists(const char *fname){
FILE *file; FILE *file;
file = fopen(fname, "r"); file = fopen(fname, "r");
if (file) if (file)
{ {
fclose(file); fclose(file);
return 1; return 1;
} }
return 0; return 0;
} }
skipping to change at line 273 skipping to change at line 304
avformat_free_context(ffmpeg->oc); avformat_free_context(ffmpeg->oc);
ffmpeg->oc = NULL; ffmpeg->oc = NULL;
} }
} }
static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){ static int ffmpeg_get_oformat(struct ffmpeg *ffmpeg){
size_t codec_name_len = strcspn(ffmpeg->codec_name, ":"); size_t codec_name_len = strcspn(ffmpeg->codec_name, ":");
char *codec_name = malloc(codec_name_len + 1); char *codec_name = malloc(codec_name_len + 1);
char basename[PATH_MAX];
int retcd;
/* TODO: Rework the extenstion asssignment along with the code in event.c
* If extension is ever something other than three bytes,
* preceded by . then lots of things will fail
*/
if (codec_name == NULL) { if (codec_name == NULL) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Failed to allocate memory for codec name")); ,_("Failed to allocate memory for codec name"));
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
return -1; return -1;
} }
memcpy(codec_name, ffmpeg->codec_name, codec_name_len); memcpy(codec_name, ffmpeg->codec_name, codec_name_len);
codec_name[codec_name_len] = 0; codec_name[codec_name_len] = 0;
/* Only the newer codec and containers can handle the really fast FPS */ /* Only the newer codec and containers can handle the really fast FPS */
skipping to change at line 295 skipping to change at line 332
(strcmp(codec_name, "mpeg4") == 0) || (strcmp(codec_name, "mpeg4") == 0) ||
(strcmp(codec_name, "swf") == 0) ) && (ffmpeg->fps >50)){ (strcmp(codec_name, "swf") == 0) ) && (ffmpeg->fps >50)){
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("The frame rate specified is too high for the ffmpeg movie type s pecified. " ,_("The frame rate specified is too high for the ffmpeg movie type s pecified. "
"Choose a different ffmpeg container or lower framerate.")); "Choose a different ffmpeg container or lower framerate."));
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
free(codec_name); free(codec_name);
return -1; return -1;
} }
retcd = snprintf(basename,PATH_MAX,"%s",ffmpeg->filename);
if ((retcd < 0) || (retcd >= PATH_MAX)){
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Error setting base file name"));
ffmpeg_free_context(ffmpeg);
free(codec_name);
return -1;
}
if (ffmpeg->tlapse == TIMELAPSE_APPEND){ if (ffmpeg->tlapse == TIMELAPSE_APPEND){
ffmpeg->oc->oformat = av_guess_format ("mpeg2video", NULL, NULL); ffmpeg->oc->oformat = av_guess_format ("mpeg2video", NULL, NULL);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ MPEG2VIDEO; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ MPEG2VIDEO;
strncat(ffmpeg->filename, ".mpg", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.mpg",basename);
if (!ffmpeg->oc->oformat) { if ((!ffmpeg->oc->oformat) ||
(retcd < 0) || (retcd >= PATH_MAX)){
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("ffmpeg_video_codec option value %s is not supported"), codec _name); ,_("Error setting timelapse append for codec %s"), codec_name);
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
free(codec_name); free(codec_name);
return -1; return -1;
} }
free(codec_name); free(codec_name);
return 0; return 0;
} }
if (strcmp(codec_name, "mpeg4") == 0) { if (strcmp(codec_name, "mpeg4") == 0) {
ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL);
strncat(ffmpeg->filename, ".avi", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.avi",basename);
} }
if (strcmp(codec_name, "msmpeg4") == 0) { if (strcmp(codec_name, "msmpeg4") == 0) {
ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL);
strncat(ffmpeg->filename, ".avi", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.avi",basename);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ MSMPEG4V2; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ MSMPEG4V2;
} }
if (strcmp(codec_name, "swf") == 0) { if (strcmp(codec_name, "swf") == 0) {
ffmpeg->oc->oformat = av_guess_format("swf", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("swf", NULL, NULL);
strncat(ffmpeg->filename, ".swf", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.swf",basename);
} }
if (strcmp(codec_name, "flv") == 0) { if (strcmp(codec_name, "flv") == 0) {
ffmpeg->oc->oformat = av_guess_format("flv", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("flv", NULL, NULL);
strncat(ffmpeg->filename, ".flv", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.flv",basename);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ FLV1; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ FLV1;
} }
if (strcmp(codec_name, "ffv1") == 0) { if (strcmp(codec_name, "ffv1") == 0) {
ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("avi", NULL, NULL);
strncat(ffmpeg->filename, ".avi", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.avi",basename);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ FFV1; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ FFV1;
} }
if (strcmp(codec_name, "mov") == 0) { if (strcmp(codec_name, "mov") == 0) {
ffmpeg->oc->oformat = av_guess_format("mov", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("mov", NULL, NULL);
strncat(ffmpeg->filename, ".mov", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.mov",basename);
} }
if (strcmp(codec_name, "mp4") == 0) { if (strcmp(codec_name, "mp4") == 0) {
ffmpeg->oc->oformat = av_guess_format("mp4", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("mp4", NULL, NULL);
strncat(ffmpeg->filename, ".mp4", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.mp4",basename);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ H264; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ H264;
} }
if (strcmp(codec_name, "mkv") == 0) { if (strcmp(codec_name, "mkv") == 0) {
ffmpeg->oc->oformat = av_guess_format("matroska", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("matroska", NULL, NULL);
strncat(ffmpeg->filename, ".mkv", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.mkv",basename);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ H264; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ H264;
} }
if (strcmp(codec_name, "hevc") == 0) { if (strcmp(codec_name, "hevc") == 0) {
ffmpeg->oc->oformat = av_guess_format("mp4", NULL, NULL); ffmpeg->oc->oformat = av_guess_format("mp4", NULL, NULL);
strncat(ffmpeg->filename, ".mp4", 4); retcd = snprintf(ffmpeg->filename,PATH_MAX,"%s.mp4",basename);
if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ HEVC; if (ffmpeg->oc->oformat) ffmpeg->oc->oformat->video_codec = MY_CODEC_ID_ HEVC;
} }
//Check for valid results //Check for valid results
if ((retcd < 0) || (retcd >= PATH_MAX)){
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Error setting file name"));
ffmpeg_free_context(ffmpeg);
free(codec_name);
return -1;
}
if (!ffmpeg->oc->oformat) { if (!ffmpeg->oc->oformat) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("codec option value %s is not supported"), codec_name); ,_("codec option value %s is not supported"), codec_name);
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
free(codec_name); free(codec_name);
return -1; return -1;
} }
if (ffmpeg->oc->oformat->video_codec == MY_CODEC_ID_NONE) { if (ffmpeg->oc->oformat->video_codec == MY_CODEC_ID_NONE) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get the codec")); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get the codec"));
skipping to change at line 412 skipping to change at line 467
return -2; return -2;
} }
if (retcd < 0 ){ if (retcd < 0 ){
av_strerror(retcd, errstr, sizeof(errstr)); av_strerror(retcd, errstr, sizeof(errstr));
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Error receiving encoded packet video:%s"),errstr); ,_("Error receiving encoded packet video:%s"),errstr);
//Packet is freed upon failure of encoding //Packet is freed upon failure of encoding
return -1; return -1;
} }
if (ffmpeg->preferred_codec == USER_CODEC_V4L2M2M){
if (ffmpeg_encode_nal(ffmpeg)) {
// Throw special return code
return -2;
}
}
return 0; return 0;
#elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6)) #elif (LIBAVFORMAT_VERSION_MAJOR >= 55) || ((LIBAVFORMAT_VERSION_MAJOR == 54) && (LIBAVFORMAT_VERSION_MINOR > 6))
int retcd = 0; int retcd = 0;
char errstr[128]; char errstr[128];
int got_packet_ptr; int got_packet_ptr;
retcd = avcodec_encode_video2(ffmpeg->ctx_codec, &ffmpeg->pkt, ffmpeg->pictu re, &got_packet_ptr); retcd = avcodec_encode_video2(ffmpeg->ctx_codec, &ffmpeg->pkt, ffmpeg->pictu re, &got_packet_ptr);
if (retcd < 0 ){ if (retcd < 0 ){
skipping to change at line 433 skipping to change at line 495
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error encoding video:%s"),err str); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error encoding video:%s"),err str);
//Packet is freed upon failure of encoding //Packet is freed upon failure of encoding
return -1; return -1;
} }
if (got_packet_ptr == 0){ if (got_packet_ptr == 0){
//Buffered packet. Throw special return code //Buffered packet. Throw special return code
my_packet_unref(ffmpeg->pkt); my_packet_unref(ffmpeg->pkt);
return -2; return -2;
} }
/* This kills compiler warnings. Nal setting is only for recent ffmpeg vers
ions*/
if (ffmpeg->preferred_codec == USER_CODEC_V4L2M2M){
if (ffmpeg_encode_nal(ffmpeg)) {
// Throw special return code
return -2;
}
}
return 0; return 0;
#else #else
int retcd = 0; int retcd = 0;
uint8_t *video_outbuf; uint8_t *video_outbuf;
int video_outbuf_size; int video_outbuf_size;
video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->hei ght +16) * 1; video_outbuf_size = (ffmpeg->ctx_codec->width +16) * (ffmpeg->ctx_codec->hei ght +16) * 1;
video_outbuf = mymalloc(video_outbuf_size); video_outbuf = mymalloc(video_outbuf_size);
skipping to change at line 468 skipping to change at line 538
ffmpeg->pkt.data = video_outbuf; ffmpeg->pkt.data = video_outbuf;
if (ffmpeg->picture->key_frame == 1) if (ffmpeg->picture->key_frame == 1)
ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY; ffmpeg->pkt.flags |= AV_PKT_FLAG_KEY;
ffmpeg->pkt.pts = ffmpeg->picture->pts; ffmpeg->pkt.pts = ffmpeg->picture->pts;
ffmpeg->pkt.dts = ffmpeg->pkt.pts; ffmpeg->pkt.dts = ffmpeg->pkt.pts;
free(video_outbuf); free(video_outbuf);
/* This kills compiler warnings. Nal setting is only for recent ffmpeg vers
ions*/
if (ffmpeg->preferred_codec == USER_CODEC_V4L2M2M){
if (ffmpeg_encode_nal(ffmpeg)) {
// Throw special return code
return -2;
}
}
return 0; return 0;
#endif #endif
} }
static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){ static int ffmpeg_set_pts(struct ffmpeg *ffmpeg, const struct timeval *tv1){
int64_t pts_interval; int64_t pts_interval;
if (ffmpeg->tlapse != TIMELAPSE_NONE) { if (ffmpeg->tlapse != TIMELAPSE_NONE) {
ffmpeg->last_pts++; ffmpeg->last_pts++;
ffmpeg->picture->pts = ffmpeg->last_pts; ffmpeg->picture->pts = ffmpeg->last_pts;
} else { } else {
pts_interval = ((1000000L * (tv1->tv_sec - ffmpeg->start_time.tv_sec)) + tv1->tv_usec - ffmpeg->start_time.tv_usec); pts_interval = ((1000000L * (tv1->tv_sec - ffmpeg->start_time.tv_sec)) + tv1->tv_usec - ffmpeg->start_time.tv_usec);
if (pts_interval < 0){ if (pts_interval < 0){
/* This can occur when we have pre-capture frames. Reset start time of video. */ /* This can occur when we have pre-capture frames. Reset start time of video. */
ffmpeg_reset_movie_start_time(ffmpeg, tv1); ffmpeg_reset_movie_start_time(ffmpeg, tv1);
pts_interval = 0; pts_interval = 0;
} }
ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000 if (ffmpeg->last_pts < 0) {
L},ffmpeg->video_st->time_base) + ffmpeg->base_pts; // This is the very first frame, ensure PTS is zero
ffmpeg->picture->pts = 0;
} else
ffmpeg->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 100
0000L},ffmpeg->video_st->time_base) + ffmpeg->base_pts;
if (ffmpeg->test_mode == TRUE){ if (ffmpeg->test_mode == TRUE){
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO
,_("PTS %"PRId64" Base PTS %"PRId64" ms interval %"PRId64" timeb ase %d-%d") ,_("PTS %"PRId64" Base PTS %"PRId64" ms interval %"PRId64" timeb ase %d-%d")
,ffmpeg->picture->pts,ffmpeg->base_pts,pts_interval ,ffmpeg->picture->pts,ffmpeg->base_pts,pts_interval
,ffmpeg->video_st->time_base.num,ffmpeg->video_st->time_base.den ); ,ffmpeg->video_st->time_base.num,ffmpeg->video_st->time_base.den );
} }
if (ffmpeg->picture->pts <= ffmpeg->last_pts){ if (ffmpeg->picture->pts <= ffmpeg->last_pts){
//We have a problem with our motion loop timing and sending frames o r the rounding into the PTS. //We have a problem with our motion loop timing and sending frames o r the rounding into the PTS.
skipping to change at line 558 skipping to change at line 640
static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){ static int ffmpeg_set_quality(struct ffmpeg *ffmpeg){
ffmpeg->opts = 0; ffmpeg->opts = 0;
if (ffmpeg->quality > 100) ffmpeg->quality = 100; if (ffmpeg->quality > 100) ffmpeg->quality = 100;
if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 || if (ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_H264 ||
ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){ ffmpeg->ctx_codec->codec_id == MY_CODEC_ID_HEVC){
if (ffmpeg->quality <= 0) if (ffmpeg->quality <= 0)
ffmpeg->quality = 45; // default to 45% quality ffmpeg->quality = 45; // default to 45% quality
av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0); av_dict_set(&ffmpeg->opts, "preset", "ultrafast", 0);
av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0); av_dict_set(&ffmpeg->opts, "tune", "zerolatency", 0);
if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) || (strcmp(ffmpeg->co /* This next if statement needs validation. Are mpeg4omx
dec->name, "mpeg4_omx") == 0)) { * and v4l2m2m even MY_CODEC_ID_H264 or MY_CODEC_ID_HEVC
// H264 OMX encoder quality can only be controlled via bit_rate * such that it even would be possible to be part of this
* if block to start with? */
if ((ffmpeg->preferred_codec == USER_CODEC_H264OMX) ||
(ffmpeg->preferred_codec == USER_CODEC_MPEG4OMX) ||
(ffmpeg->preferred_codec == USER_CODEC_V4L2M2M)) {
// bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality _factor // bit_rate = ffmpeg->width * ffmpeg->height * ffmpeg->fps * quality _factor
ffmpeg->quality = (ffmpeg->width * ffmpeg->height * ffmpeg->fps * ff mpeg->quality) >> 7; ffmpeg->quality = (int)(((int64_t)ffmpeg->width * ffmpeg->height * f fmpeg->fps * ffmpeg->quality) >> 7);
// Clip bit rate to min // Clip bit rate to min
if (ffmpeg->quality < 4000) // magic number if (ffmpeg->quality < 4000) // magic number
ffmpeg->quality = 4000; ffmpeg->quality = 4000;
ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH; ffmpeg->ctx_codec->profile = FF_PROFILE_H264_HIGH;
ffmpeg->ctx_codec->bit_rate = ffmpeg->quality; ffmpeg->ctx_codec->bit_rate = ffmpeg->quality;
} else { } else {
// Control other H264 encoders quality via CRF // Control other H264 encoders quality via CRF
char crf[10]; char crf[10];
ffmpeg->quality = (int)(( (100-ffmpeg->quality) * 51)/100); ffmpeg->quality = (int)(( (100-ffmpeg->quality) * 51)/100);
snprintf(crf, 10, "%d", ffmpeg->quality); snprintf(crf, 10, "%d", ffmpeg->quality);
skipping to change at line 588 skipping to change at line 675
ffmpeg->ctx_codec->flags |= MY_CODEC_FLAG_QSCALE; ffmpeg->ctx_codec->flags |= MY_CODEC_FLAG_QSCALE;
ffmpeg->ctx_codec->global_quality=ffmpeg->quality; ffmpeg->ctx_codec->global_quality=ffmpeg->quality;
} }
} }
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO
,_("%s codec vbr/crf/bit_rate: %d"), ffmpeg->codec->name, ffmpeg->qualit y); ,_("%s codec vbr/crf/bit_rate: %d"), ffmpeg->codec->name, ffmpeg->qualit y);
return 0; return 0;
} }
static int ffmpeg_codec_is_blacklisted(const char *codec_name){ struct blacklist_t
{
const char *codec_name;
const char *reason;
};
static const char *ffmpeg_codec_is_blacklisted(const char *codec_name){
static const char *blacklisted_codec[] = static struct blacklist_t blacklisted_codec[] =
{ {
#if (LIBAVFORMAT_VERSION_MAJOR < 58) || ( (LIBAVFORMAT_VERSION_MAJOR == 58) && ( (LIBAVFORMAT_VERSION_MINOR < 29) || ((LIBAVFORMAT_VERSION_MINOR == 29) && (LIBA VFORMAT_VERSION_MICRO <= 100)) ) )
/* h264_omx & ffmpeg combination locks up on Raspberry Pi. /* h264_omx & ffmpeg combination locks up on Raspberry Pi.
* To use h264_omx encoder and workaround the lock up issue: * Newer versions of ffmpeg allow zerocopy to be disabled to workaround
* this issue.
* To use h264_omx encoder on older versions of ffmpeg:
* - disable input_zerocopy in ffmpeg omx.c:omx_encode_init function. * - disable input_zerocopy in ffmpeg omx.c:omx_encode_init function.
* - remove the "h264_omx" from this blacklist. * - remove the "h264_omx" from this blacklist.
* More information: https://github.com/Motion-Project/motion/issues/433 * More information: https://github.com/Motion-Project/motion/issues/433
*/ */
"h264_omx", {"h264_omx", "Codec causes lock up on your FFMpeg version"},
#endif
#if (LIBAVFORMAT_VERSION_MAJOR < 57) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && (L
IBAVFORMAT_VERSION_MINOR < 41))
{"h264_v4l2m2m", "FFMpeg version is too old"},
#endif
}; };
size_t i; size_t i;
for (i = 0; i < sizeof(blacklisted_codec)/sizeof(blacklisted_codec[0]); i++) { for (i = 0; i < sizeof(blacklisted_codec)/sizeof(blacklisted_codec[0]); i++) {
if (strcmp(codec_name, blacklisted_codec[i]) == 0) if (strcmp(codec_name, blacklisted_codec[i].codec_name) == 0)
return 1; return blacklisted_codec[i].reason;
} }
return 0; return NULL;
} }
static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){ static int ffmpeg_set_codec_preferred(struct ffmpeg *ffmpeg){
int retcd;
char errstr[128];
int chkrate;
size_t codec_name_len = strcspn(ffmpeg->codec_name, ":"); size_t codec_name_len = strcspn(ffmpeg->codec_name, ":");
ffmpeg->codec = NULL; ffmpeg->codec = NULL;
if (ffmpeg->codec_name[codec_name_len]) { if (ffmpeg->codec_name[codec_name_len]) {
if (ffmpeg_codec_is_blacklisted(&ffmpeg->codec_name[codec_name_len+1])) const char *blacklist_reason = ffmpeg_codec_is_blacklisted(&ffmpeg->code
{ c_name[codec_name_len+1]);
if (blacklist_reason) {
MOTION_LOG(WRN, TYPE_ENCODER, NO_ERRNO MOTION_LOG(WRN, TYPE_ENCODER, NO_ERRNO
,_("Preferred codec %s has been blacklisted") ,_("Preferred codec %s has been blacklisted: %s")
,&ffmpeg->codec_name[codec_name_len+1]); ,&ffmpeg->codec_name[codec_name_len+1], blacklist_reason);
} else { } else {
ffmpeg->codec = avcodec_find_encoder_by_name(&ffmpeg->codec_name[cod ec_name_len+1]); ffmpeg->codec = avcodec_find_encoder_by_name(&ffmpeg->codec_name[cod ec_name_len+1]);
if ((ffmpeg->oc->oformat) && (ffmpeg->codec != NULL)) { if ((ffmpeg->oc->oformat) && (ffmpeg->codec != NULL)) {
ffmpeg->oc->oformat->video_codec = ffmpeg->codec->id; ffmpeg->oc->oformat->video_codec = ffmpeg->codec->id;
} else if (ffmpeg->codec == NULL) { } else if (ffmpeg->codec == NULL) {
MOTION_LOG(WRN, TYPE_ENCODER, NO_ERRNO MOTION_LOG(WRN, TYPE_ENCODER, NO_ERRNO
,_("Preferred codec %s not found") ,_("Preferred codec %s not found")
,&ffmpeg->codec_name[codec_name_len+1]); ,&ffmpeg->codec_name[codec_name_len+1]);
} }
} }
} }
if (!ffmpeg->codec) if (!ffmpeg->codec)
ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec); ffmpeg->codec = avcodec_find_encoder(ffmpeg->oc->oformat->video_codec);
if (!ffmpeg->codec) { if (!ffmpeg->codec) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Codec %s not found"), ffmpeg->codec_name); ,_("Codec %s not found"), ffmpeg->codec_name);
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
return -1; return -1;
} }
if (strcmp(ffmpeg->codec->name, "h264_v4l2m2m") == 0){
ffmpeg->preferred_codec = USER_CODEC_V4L2M2M;
} else if (strcmp(ffmpeg->codec->name, "h264_omx") == 0){
ffmpeg->preferred_codec = USER_CODEC_H264OMX;
} else if (strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0){
ffmpeg->preferred_codec = USER_CODEC_MPEG4OMX;
} else {
ffmpeg->preferred_codec = USER_CODEC_DEFAULT;
}
if (ffmpeg->codec_name[codec_name_len]) if (ffmpeg->codec_name[codec_name_len])
MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO,_("Using codec %s"), ffmpeg->code c->name); MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO,_("Using codec %s"), ffmpeg->code c->name);
return 0;
}
static int ffmpeg_set_codec(struct ffmpeg *ffmpeg){
int retcd;
char errstr[128];
int chkrate;
retcd = ffmpeg_set_codec_preferred(ffmpeg);
if (retcd != 0) return retcd;
#if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && ( LIBAVFORMAT_VERSION_MINOR >= 41)) #if (LIBAVFORMAT_VERSION_MAJOR >= 58) || ((LIBAVFORMAT_VERSION_MAJOR == 57) && ( LIBAVFORMAT_VERSION_MINOR >= 41))
//If we provide the codec to this, it results in a memory leak. ffmpeg tick et: 5714 //If we provide the codec to this, it results in a memory leak. ffmpeg tick et: 5714
ffmpeg->video_st = avformat_new_stream(ffmpeg->oc, NULL); ffmpeg->video_st = avformat_new_stream(ffmpeg->oc, NULL);
if (!ffmpeg->video_st) { if (!ffmpeg->video_st) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc stream")); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc stream"));
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
return -1; return -1;
} }
ffmpeg->ctx_codec = avcodec_alloc_context3(ffmpeg->codec); ffmpeg->ctx_codec = avcodec_alloc_context3(ffmpeg->codec);
if (ffmpeg->ctx_codec == NULL) { if (ffmpeg->ctx_codec == NULL) {
skipping to change at line 692 skipping to change at line 813
** a very poor quality playback. We can set the FPS to a higher number and ** a very poor quality playback. We can set the FPS to a higher number and
** then let the PTS display the frames correctly. ** then let the PTS display the frames correctly.
*/ */
if ((ffmpeg->tlapse == TIMELAPSE_NONE) && (ffmpeg->fps <= 5)){ if ((ffmpeg->tlapse == TIMELAPSE_NONE) && (ffmpeg->fps <= 5)){
if ((strcmp(ffmpeg->codec_name, "msmpeg4") == 0) || if ((strcmp(ffmpeg->codec_name, "msmpeg4") == 0) ||
(strcmp(ffmpeg->codec_name, "flv") == 0) || (strcmp(ffmpeg->codec_name, "flv") == 0) ||
(strcmp(ffmpeg->codec_name, "mov") == 0) || (strcmp(ffmpeg->codec_name, "mov") == 0) ||
(strcmp(ffmpeg->codec_name, "mp4") == 0) || (strcmp(ffmpeg->codec_name, "mp4") == 0) ||
(strcmp(ffmpeg->codec_name, "hevc") == 0) || (strcmp(ffmpeg->codec_name, "hevc") == 0) ||
(strcmp(ffmpeg->codec_name, "mpeg4") == 0)) { (strcmp(ffmpeg->codec_name, "mpeg4") == 0)) {
MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO, "Low fps. Encoding %d frames into a %d frames container.", ffmpeg->fps, 10); MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO, _("Low fps. Encoding %d fram es into a %d frames container."), ffmpeg->fps, 10);
ffmpeg->fps = 10; ffmpeg->fps = 10;
} }
} }
ffmpeg->ctx_codec->codec_id = ffmpeg->oc->oformat->video_codec; ffmpeg->ctx_codec->codec_id = ffmpeg->oc->oformat->video_codec;
ffmpeg->ctx_codec->codec_type = AVMEDIA_TYPE_VIDEO; ffmpeg->ctx_codec->codec_type = AVMEDIA_TYPE_VIDEO;
ffmpeg->ctx_codec->bit_rate = ffmpeg->bps; ffmpeg->ctx_codec->bit_rate = ffmpeg->bps;
ffmpeg->ctx_codec->width = ffmpeg->width; ffmpeg->ctx_codec->width = ffmpeg->width;
ffmpeg->ctx_codec->height = ffmpeg->height; ffmpeg->ctx_codec->height = ffmpeg->height;
ffmpeg->ctx_codec->time_base.num = 1; ffmpeg->ctx_codec->time_base.num = 1;
ffmpeg->ctx_codec->time_base.den = ffmpeg->fps; ffmpeg->ctx_codec->time_base.den = ffmpeg->fps;
ffmpeg->ctx_codec->pix_fmt = MY_PIX_FMT_YUV420P; if (ffmpeg->preferred_codec == USER_CODEC_V4L2M2M){
ffmpeg->ctx_codec->pix_fmt = AV_PIX_FMT_NV21;
} else {
ffmpeg->ctx_codec->pix_fmt = MY_PIX_FMT_YUV420P;
}
ffmpeg->ctx_codec->max_b_frames = 0; ffmpeg->ctx_codec->max_b_frames = 0;
if (strcmp(ffmpeg->codec_name, "ffv1") == 0){ if (strcmp(ffmpeg->codec_name, "ffv1") == 0){
ffmpeg->ctx_codec->strict_std_compliance = -2; ffmpeg->ctx_codec->strict_std_compliance = -2;
ffmpeg->ctx_codec->level = 3; ffmpeg->ctx_codec->level = 3;
} }
ffmpeg->ctx_codec->flags |= MY_CODEC_FLAG_GLOBAL_HEADER; ffmpeg->ctx_codec->flags |= MY_CODEC_FLAG_GLOBAL_HEADER;
if ((strcmp(ffmpeg->codec->name, "h264_omx") == 0) ||
(strcmp(ffmpeg->codec->name, "mpeg4_omx") == 0)) {
/* h264_omx & ffmpeg combination locks up on Raspberry Pi.
* To use h264_omx encoder, we need to disable zerocopy.
* More information: https://github.com/Motion-Project/motion/issues/433
*/
av_dict_set(&ffmpeg->opts, "zerocopy", "0", 0);
}
retcd = ffmpeg_set_quality(ffmpeg); retcd = ffmpeg_set_quality(ffmpeg);
if (retcd < 0){ if (retcd < 0){
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Unable to set quality")); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Unable to set quality"));
return -1; return -1;
} }
retcd = avcodec_open2(ffmpeg->ctx_codec, ffmpeg->codec, &ffmpeg->opts); retcd = avcodec_open2(ffmpeg->ctx_codec, ffmpeg->codec, &ffmpeg->opts);
if (retcd < 0) { if (retcd < 0) {
if (ffmpeg->codec->supported_framerates) { if (ffmpeg->codec->supported_framerates) {
const AVRational *fps = ffmpeg->codec->supported_framerates; const AVRational *fps = ffmpeg->codec->supported_framerates;
skipping to change at line 770 skipping to change at line 904
return -1; return -1;
} }
#endif #endif
ffmpeg->video_st->time_base = (AVRational){1, ffmpeg->fps}; ffmpeg->video_st->time_base = (AVRational){1, ffmpeg->fps};
return 0; return 0;
} }
/*Special allocation of video buffer for v4l2m2m codec*/
static int ffmpeg_alloc_video_buffer(AVFrame *frame, int align)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
int ret, i, padded_height;
int plane_padding = FFMAX(16 + 16/*STRIDE_ALIGN*/, align);
if (!desc)
return AVERROR(EINVAL);
if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0)
return ret;
if (!frame->linesize[0]) {
if (align <= 0)
align = 32; /* STRIDE_ALIGN. Should be av_cpu_max_align() */
for(i=1; i<=align; i+=i) {
ret = av_image_fill_linesizes(frame->linesize, frame->format,
FFALIGN(frame->width, i));
if (ret < 0)
return ret;
if (!(frame->linesize[0] & (align-1)))
break;
}
for (i = 0; i < 4 && frame->linesize[i]; i++)
frame->linesize[i] = FFALIGN(frame->linesize[i], align);
}
padded_height = FFALIGN(frame->height, 32);
if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height,
NULL, frame->linesize)) < 0)
return ret;
frame->buf[0] = av_buffer_alloc(ret + 4*plane_padding);
if (!frame->buf[0]) {
ret = AVERROR(ENOMEM);
av_frame_unref(frame);
return ret;
}
frame->buf[1] = av_buffer_alloc(ret + 4*plane_padding);
if (!frame->buf[1]) {
ret = AVERROR(ENOMEM);
av_frame_unref(frame);
return ret;
}
frame->data[0] = frame->buf[0]->data;
frame->data[1] = frame->buf[1]->data;
frame->data[2] = frame->data[1] + ((frame->width * padded_height) / 4);
frame->extended_data = frame->data;
return 0;
}
static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){ static int ffmpeg_set_picture(struct ffmpeg *ffmpeg){
int retcd;
char errstr[128];
ffmpeg->picture = my_frame_alloc(); ffmpeg->picture = my_frame_alloc();
if (!ffmpeg->picture) { if (!ffmpeg->picture) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc frame")); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc frame"));
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
return -1; return -1;
} }
/* Take care of variable bitrate setting. */ /* Take care of variable bitrate setting. */
if (ffmpeg->quality) if (ffmpeg->quality)
ffmpeg->picture->quality = ffmpeg->quality; ffmpeg->picture->quality = ffmpeg->quality;
ffmpeg->picture->linesize[0] = ffmpeg->ctx_codec->width; ffmpeg->picture->linesize[0] = ffmpeg->ctx_codec->width;
ffmpeg->picture->linesize[1] = ffmpeg->ctx_codec->width / 2; ffmpeg->picture->linesize[1] = ffmpeg->ctx_codec->width / 2;
ffmpeg->picture->linesize[2] = ffmpeg->ctx_codec->width / 2; ffmpeg->picture->linesize[2] = ffmpeg->ctx_codec->width / 2;
ffmpeg->picture->format = ffmpeg->ctx_codec->pix_fmt; ffmpeg->picture->format = ffmpeg->ctx_codec->pix_fmt;
ffmpeg->picture->width = ffmpeg->ctx_codec->width; ffmpeg->picture->width = ffmpeg->ctx_codec->width;
ffmpeg->picture->height = ffmpeg->ctx_codec->height; ffmpeg->picture->height = ffmpeg->ctx_codec->height;
if (ffmpeg->preferred_codec == USER_CODEC_V4L2M2M) {
retcd = ffmpeg_alloc_video_buffer(ffmpeg->picture, 32);
if (retcd) {
av_strerror(retcd, errstr, sizeof(errstr));
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("could not alloc buffers %
s"), errstr);
ffmpeg_free_context(ffmpeg);
return -1;
}
}
return 0; return 0;
} }
static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){ static int ffmpeg_set_outputfile(struct ffmpeg *ffmpeg){
int retcd; int retcd;
char errstr[128]; char errstr[128];
#if (LIBAVFORMAT_VERSION_MAJOR < 58) #if (LIBAVFORMAT_VERSION_MAJOR < 58)
skipping to change at line 893 skipping to change at line 1097
ffmpeg->pkt.size = 0; ffmpeg->pkt.size = 0;
recv_cd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt); recv_cd = avcodec_receive_packet(ffmpeg->ctx_codec, &ffmpeg->pkt);
if (recv_cd != AVERROR_EOF){ if (recv_cd != AVERROR_EOF){
if (recv_cd < 0){ if (recv_cd < 0){
av_strerror(recv_cd, errstr, sizeof(errstr)); av_strerror(recv_cd, errstr, sizeof(errstr));
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Error draining codec:%s"),errstr); ,_("Error draining codec:%s"),errstr);
my_packet_unref(ffmpeg->pkt); my_packet_unref(ffmpeg->pkt);
return -1; return -1;
} }
// v4l2_m2m encoder uses pts 0 and size 0 to indicate AVERROR_EO
F
if ((ffmpeg->pkt.pts == 0) || (ffmpeg->pkt.size == 0)) {
recv_cd = AVERROR_EOF;
my_packet_unref(ffmpeg->pkt);
continue;
}
retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt); retcd = av_write_frame(ffmpeg->oc, &ffmpeg->pkt);
if (retcd < 0) { if (retcd < 0) {
MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO
,_("Error writing draining video frame")); ,_("Error writing draining video frame"));
return -1; return -1;
} }
} }
my_packet_unref(ffmpeg->pkt); my_packet_unref(ffmpeg->pkt);
} }
} }
skipping to change at line 979 skipping to change at line 1189
av_init_packet(&ffmpeg->pkt); av_init_packet(&ffmpeg->pkt);
ffmpeg->pkt.data = NULL; ffmpeg->pkt.data = NULL;
ffmpeg->pkt.size = 0; ffmpeg->pkt.size = 0;
ffmpeg->rtsp_data->pktarray[indx].iswritten = TRUE; ffmpeg->rtsp_data->pktarray[indx].iswritten = TRUE;
retcd = my_copy_packet(&ffmpeg->pkt, &ffmpeg->rtsp_data->pktarray[indx].pack et); retcd = my_copy_packet(&ffmpeg->pkt, &ffmpeg->rtsp_data->pktarray[indx].pack et);
if (retcd < 0) { if (retcd < 0) {
av_strerror(retcd, errstr, sizeof(errstr)); av_strerror(retcd, errstr, sizeof(errstr));
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "av_copy_packet: %s",errstr); MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("av_copy_packet: %s"),errstr);
my_packet_unref(ffmpeg->pkt); my_packet_unref(ffmpeg->pkt);
return; return;
} }
retcd = ffmpeg_set_pktpts(ffmpeg, &ffmpeg->rtsp_data->pktarray[indx].timesta mp_tv); retcd = ffmpeg_set_pktpts(ffmpeg, &ffmpeg->rtsp_data->pktarray[indx].timesta mp_tv);
if (retcd < 0) { if (retcd < 0) {
my_packet_unref(ffmpeg->pkt); my_packet_unref(ffmpeg->pkt);
return; return;
} }
skipping to change at line 1153 skipping to change at line 1363
ffmpeg->video_st->codec->codec_tag = 0; ffmpeg->video_st->codec->codec_tag = 0;
#else #else
/* This is disabled in the util_check_passthrough but we need it here fo r compiling */ /* This is disabled in the util_check_passthrough but we need it here fo r compiling */
pthread_mutex_unlock(&ffmpeg->rtsp_data->mutex_transfer); pthread_mutex_unlock(&ffmpeg->rtsp_data->mutex_transfer);
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("Pass-through disabled. ffmpe g too old")); MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("Pass-through disabled. ffmpe g too old"));
return -1; return -1;
#endif #endif
ffmpeg->video_st->time_base = stream_in->time_base; ffmpeg->video_st->time_base = stream_in->time_base;
pthread_mutex_unlock(&ffmpeg->rtsp_data->mutex_transfer); pthread_mutex_unlock(&ffmpeg->rtsp_data->mutex_transfer);
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "Pass-through stream opened"); MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("Pass-through stream opened"));
return 0; return 0;
} }
void ffmpeg_avcodec_log(void *ignoreme ATTRIBUTE_UNUSED, int errno_flag ATTRIBUT E_UNUSED, const char *fmt, va_list vl){ void ffmpeg_avcodec_log(void *ignoreme ATTRIBUTE_UNUSED, int errno_flag ATTRIBUT E_UNUSED, const char *fmt, va_list vl){
char buf[1024]; char buf[1024];
char *end; char *end;
/* Valgrind occasionally reports use of uninitialized values in here when we interrupt /* Valgrind occasionally reports use of uninitialized values in here when we interrupt
skipping to change at line 1182 skipping to change at line 1392
end = buf + strlen(buf); end = buf + strlen(buf);
if (end > buf && end[-1] == '\n') if (end > buf && end[-1] == '\n')
{ {
*--end = 0; *--end = 0;
} }
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "%s", buf); MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "%s", buf);
} }
} }
static void ffmpeg_put_pix_nv21(struct ffmpeg *ffmpeg, struct image_data *img_da
ta){
unsigned char *image,*imagecr, *imagecb;
int cr_len, x, y;
if (ffmpeg->high_resolution){
image = img_data->image_high;
} else {
image = img_data->image_norm;
}
cr_len = ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height / 4;
imagecr = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height);
imagecb = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_codec->height) + c
r_len;
memcpy(ffmpeg->picture->data[0], image, ffmpeg->ctx_codec->width * ffmpeg->c
tx_codec->height);
for (y = 0; y < ffmpeg->ctx_codec->height; y++) {
for (x = 0; x < ffmpeg->ctx_codec->width/4; x++) {
ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2] = *imag
ecb;
ffmpeg->picture->data[1][y*ffmpeg->ctx_codec->width/2 + x*2 + 1] = *
imagecr;
imagecb++;
imagecr++;
}
}
}
static void ffmpeg_put_pix_yuv420(struct ffmpeg *ffmpeg, struct image_data *img_
data){
unsigned char *image;
if (ffmpeg->high_resolution){
image = img_data->image_high;
} else {
image = img_data->image_norm;
}
// Usual setup for image pointers
ffmpeg->picture->data[0] = image;
ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->ctx_c
odec->height);
ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_codec->w
idth * ffmpeg->ctx_codec->height) / 4);
}
#endif /* HAVE_FFMPEG */ #endif /* HAVE_FFMPEG */
/**************************************************************************** /****************************************************************************
**************************************************************************** ****************************************************************************
****************************************************************************/ ****************************************************************************/
void ffmpeg_global_init(void){ void ffmpeg_global_init(void){
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO
skipping to change at line 1334 skipping to change at line 1586
if (ffmpeg->tlapse != TIMELAPSE_APPEND) { if (ffmpeg->tlapse != TIMELAPSE_APPEND) {
av_write_trailer(ffmpeg->oc); av_write_trailer(ffmpeg->oc);
} }
if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) { if (!(ffmpeg->oc->oformat->flags & AVFMT_NOFILE)) {
if (ffmpeg->tlapse != TIMELAPSE_APPEND) { if (ffmpeg->tlapse != TIMELAPSE_APPEND) {
avio_close(ffmpeg->oc->pb); avio_close(ffmpeg->oc->pb);
} }
} }
} }
ffmpeg_free_context(ffmpeg); ffmpeg_free_context(ffmpeg);
ffmpeg_free_nal(ffmpeg);
} }
#else #else
if (ffmpeg != NULL) free(ffmpeg); if (ffmpeg != NULL) free(ffmpeg);
#endif // HAVE_FFMPEG #endif // HAVE_FFMPEG
} }
int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s truct timeval *tv1){ int ffmpeg_put_image(struct ffmpeg *ffmpeg, struct image_data *img_data, const s truct timeval *tv1){
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
int retcd = 0; int retcd = 0;
int cnt = 0; int cnt = 0;
unsigned char *image;
if (ffmpeg->passthrough) { if (ffmpeg->passthrough) {
retcd = ffmpeg_passthru_put(ffmpeg, img_data); retcd = ffmpeg_passthru_put(ffmpeg, img_data);
return retcd; return retcd;
} }
if (ffmpeg->picture) { if (ffmpeg->picture) {
if (ffmpeg->high_resolution){
image = img_data->image_high; if (ffmpeg->preferred_codec == USER_CODEC_V4L2M2M) {
ffmpeg_put_pix_nv21(ffmpeg, img_data);
} else { } else {
image = img_data->image_norm; ffmpeg_put_pix_yuv420(ffmpeg, img_data);
} }
/* Setup pointers and line widths. */
ffmpeg->picture->data[0] = image;
ffmpeg->picture->data[1] = image + (ffmpeg->ctx_codec->width * ffmpeg->c
tx_codec->height);
ffmpeg->picture->data[2] = ffmpeg->picture->data[1] + ((ffmpeg->ctx_code
c->width * ffmpeg->ctx_codec->height) / 4);
ffmpeg->gop_cnt ++; ffmpeg->gop_cnt ++;
if (ffmpeg->gop_cnt == ffmpeg->ctx_codec->gop_size ){ if (ffmpeg->gop_cnt == ffmpeg->ctx_codec->gop_size ){
ffmpeg->picture->pict_type = AV_PICTURE_TYPE_I; ffmpeg->picture->pict_type = AV_PICTURE_TYPE_I;
ffmpeg->picture->key_frame = 1; ffmpeg->picture->key_frame = 1;
ffmpeg->gop_cnt = 0; ffmpeg->gop_cnt = 0;
} else { } else {
ffmpeg->picture->pict_type = AV_PICTURE_TYPE_P; ffmpeg->picture->pict_type = AV_PICTURE_TYPE_P;
ffmpeg->picture->key_frame = 0; ffmpeg->picture->key_frame = 0;
} }
 End of changes. 49 change blocks. 
49 lines changed or deleted 309 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)