From 52a4755be1bdbb09edb252608df15210e661aff4 Mon Sep 17 00:00:00 2001 From: MrDave Date: Sun, 10 Jan 2021 17:59:03 -0700 Subject: [PATCH] Experimental sound --- src/movie.cpp | 361 ++++++++++++++++++++++++++++--------------------- src/movie.hpp | 3 +- src/netcam.cpp | 95 +++++++------ src/netcam.hpp | 2 + src/util.cpp | 17 +-- 5 files changed, 274 insertions(+), 204 deletions(-) diff --git a/src/movie.cpp b/src/movie.cpp index 52d73eaa..578ced48 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -298,7 +298,7 @@ static int movie_encode_video(struct ctx_movie *movie) video_outbuf_size = (movie->ctx_codec->width +16) * (movie->ctx_codec->height +16) * 1; video_outbuf =(uint8_t *) mymalloc(video_outbuf_size); - retcd = avcodec_encode_video(movie->video_st->codec, video_outbuf, video_outbuf_size, movie->picture); + retcd = avcodec_encode_video(movie->strm_video->codec, video_outbuf, video_outbuf_size, movie->picture); if (retcd < 0 ){ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Error encoding video")); mypacket_unref(movie->pkt); @@ -352,13 +352,13 @@ static int movie_set_pts(struct ctx_movie *movie, const struct timespec *ts1) // This is the very first frame, ensure PTS is zero movie->picture->pts = 0; } else - movie->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},movie->video_st->time_base) + movie->base_pts; + movie->picture->pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},movie->strm_video->time_base) + movie->base_pts; if (movie->test_mode == TRUE){ MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO ,_("PTS %" PRId64 " Base PTS %" PRId64 " ms interval %" PRId64 " timebase %d-%d") ,movie->picture->pts,movie->base_pts,pts_interval - ,movie->video_st->time_base.num,movie->video_st->time_base.den); + ,movie->strm_video->time_base.num,movie->strm_video->time_base.den); } if (movie->picture->pts <= movie->last_pts){ @@ -373,46 +373,6 @@ static int movie_set_pts(struct ctx_movie *movie, const struct timespec *ts1) return 0; } -static int movie_set_pktpts(struct ctx_movie *movie, const struct timespec *ts1) -{ - - int64_t pts_interval; - - if (movie->tlapse != TIMELAPSE_NONE) { - movie->last_pts++; - movie->pkt.pts = movie->last_pts; - } else { - pts_interval = ((1000000L * (ts1->tv_sec - movie->start_time.tv_sec)) + (ts1->tv_nsec/1000) - (movie->start_time.tv_nsec/1000)); - if (pts_interval < 0){ - /* This can occur when we have pre-capture frames. Reset start time of video. */ - movie_reset_start_time(movie, ts1); - pts_interval = 0; - } - movie->pkt.pts = av_rescale_q(pts_interval,(AVRational){1, 1000000L},movie->video_st->time_base) + movie->base_pts; - - if (movie->test_mode == TRUE){ - MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO - ,_("PTS %" PRId64 " Base PTS %" PRId64 " ms interval %" PRId64 " timebase %d-%d Change %d") - ,movie->pkt.pts - ,movie->base_pts,pts_interval - ,movie->video_st->time_base.num - ,movie->video_st->time_base.den - ,(movie->pkt.pts-movie->last_pts) ); - } - - if (movie->pkt.pts <= movie->last_pts){ - //We have a problem with our motion loop timing and sending frames or the rounding into the PTS. - if (movie->test_mode == TRUE){ - MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("BAD TIMING!! Frame skipped.")); - } - return -1; - } - movie->last_pts = movie->pkt.pts; - movie->pkt.dts=movie->pkt.pts; - } - return 0; -} - static int movie_set_quality(struct ctx_movie *movie) { @@ -566,8 +526,8 @@ static int movie_set_codec(struct ctx_movie *movie) #if (MYFFVER >= 57041) //If we provide the codec to this, it results in a memory leak. ffmpeg ticket: 5714 - movie->video_st = avformat_new_stream(movie->oc, NULL); - if (!movie->video_st) { + movie->strm_video = avformat_new_stream(movie->oc, NULL); + if (!movie->strm_video) { MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc stream")); movie_free_context(movie); return -1; @@ -579,13 +539,13 @@ static int movie_set_codec(struct ctx_movie *movie) return -1; } #else - movie->video_st = avformat_new_stream(movie->oc, movie->codec); - if (!movie->video_st) { + movie->strm_video = avformat_new_stream(movie->oc, movie->codec); + if (!movie->strm_video) { MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc stream")); movie_free_context(movie); return -1; } - movie->ctx_codec = movie->video_st->codec; + movie->ctx_codec = movie->strm_video->codec; #endif @@ -686,7 +646,7 @@ static int movie_set_stream(struct ctx_movie *movie) int retcd; char errstr[128]; - retcd = avcodec_parameters_from_context(movie->video_st->codecpar,movie->ctx_codec); + retcd = avcodec_parameters_from_context(movie->strm_video->codecpar,movie->ctx_codec); if (retcd < 0) { av_strerror(retcd, errstr, sizeof(errstr)); MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO @@ -696,7 +656,7 @@ static int movie_set_stream(struct ctx_movie *movie) } #endif - movie->video_st->time_base = (AVRational){1, movie->fps}; + movie->strm_video->time_base = (AVRational){1, movie->fps}; return 0; @@ -971,9 +931,9 @@ static int movie_put_frame(struct ctx_movie *movie, const struct timespec *ts1) } +/* Reset the written flag and movie start time at opening of each event */ static void movie_passthru_reset(struct ctx_movie *movie) { - /* Reset the written flag at start of each event */ int indx; pthread_mutex_lock(&movie->netcam_data->mutex_pktarray); @@ -984,6 +944,36 @@ static void movie_passthru_reset(struct ctx_movie *movie) } + +static int movie_passthru_pktpts(struct ctx_movie *movie) +{ + int64_t ts_interval; + AVRational tmpbase; + int indx; + + if (movie->pkt.stream_index == movie->netcam_data->audio_stream_index) { + tmpbase = movie->strm_audio->time_base; + indx = movie->netcam_data->audio_stream_index; + } else { + tmpbase = movie->strm_video->time_base; + indx = movie->netcam_data->video_stream_index; + } + + ts_interval = movie->pkt.pts; + movie->pkt.pts = av_rescale_q(ts_interval + , movie->netcam_data->transfer_format->streams[indx]->time_base, tmpbase); + + ts_interval = movie->pkt.dts; + movie->pkt.dts = av_rescale_q(ts_interval + , movie->netcam_data->transfer_format->streams[indx]->time_base, tmpbase); + + ts_interval = movie->pkt.duration; + movie->pkt.duration = av_rescale_q(ts_interval + , movie->netcam_data->transfer_format->streams[indx]->time_base, tmpbase); + + return 0; +} + static void movie_passthru_write(struct ctx_movie *movie, int indx) { /* Write the packet in the buffer at indx to file */ @@ -994,7 +984,6 @@ static void movie_passthru_write(struct ctx_movie *movie, int indx) movie->pkt.data = NULL; movie->pkt.size = 0; - movie->netcam_data->pktarray[indx].iswritten = TRUE; retcd = mycopy_packet(&movie->pkt, &movie->netcam_data->pktarray[indx].packet); @@ -1005,14 +994,12 @@ static void movie_passthru_write(struct ctx_movie *movie, int indx) return; } - retcd = movie_set_pktpts(movie, &movie->netcam_data->pktarray[indx].timestamp_ts); + retcd = movie_passthru_pktpts(movie); if (retcd < 0) { mypacket_unref(movie->pkt); return; } - movie->pkt.stream_index = 0; - retcd = av_write_frame(movie->oc, &movie->pkt); mypacket_unref(movie->pkt); if (retcd < 0) { @@ -1026,7 +1013,6 @@ static void movie_passthru_write(struct ctx_movie *movie, int indx) static int movie_passthru_put(struct ctx_movie *movie, struct ctx_image_data *img_data) { - int idnbr_image, idnbr_lastwritten, idnbr_stop, idnbr_firstkey; int indx, indx_lastwritten, indx_firstkey; @@ -1095,90 +1081,164 @@ static int movie_passthru_put(struct ctx_movie *movie, struct ctx_image_data *im return 0; } -static int movie_passthru_codec(struct ctx_movie *movie) +static int movie_passthru_streams_video(struct ctx_movie *movie, AVStream *stream_in) { + int retcd; - int retcd; - AVStream *stream_in; + movie->strm_video = avformat_new_stream(movie->oc, NULL); + if (!movie->strm_video) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc video stream")); + return -1; + } + + retcd = avcodec_parameters_copy(movie->strm_video->codecpar, stream_in->codecpar); + if (retcd < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Unable to copy video codec parameters")); + return -1; + } + + movie->strm_video->codecpar->codec_tag = 0; + movie->strm_video->time_base = stream_in->time_base; + + MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO + , _("video timebase %d/%d") + , movie->strm_video->time_base.num + , movie->strm_video->time_base.den); + + return 0; +} + +static int movie_passthru_streams_audio(struct ctx_movie *movie, AVStream *stream_in) +{ + int retcd; + + movie->strm_audio = avformat_new_stream(movie->oc, NULL); + if (!movie->strm_audio) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc audio stream")); + return -1; + } + + retcd = avcodec_parameters_copy(movie->strm_audio->codecpar, stream_in->codecpar); + if (retcd < 0) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Unable to copy audio codec parameters")); + return -1; + } + + movie->strm_audio->codecpar->codec_tag = 0; + movie->strm_audio->time_base = stream_in->time_base; + movie->strm_audio->r_frame_rate = stream_in->time_base; + movie->strm_audio->avg_frame_rate= stream_in->time_base; + movie->strm_audio->codecpar->format = stream_in->codecpar->format; + movie->strm_audio->codecpar->sample_rate = stream_in->codecpar->sample_rate; + + MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO + , _("audio timebase %d/%d") + , movie->strm_audio->time_base.num + , movie->strm_audio->time_base.den); + return 0; +} + +static int movie_passthru_streams(struct ctx_movie *movie) +{ + #if (MYFFVER >= 57041) + int retcd, indx; + AVStream *stream_in; + + pthread_mutex_lock(&movie->netcam_data->mutex_transfer); + for (indx= 0; indx < (int)movie->netcam_data->transfer_format->nb_streams; indx++) { + stream_in = movie->netcam_data->transfer_format->streams[indx]; + movie->oc->oformat->video_codec = stream_in->codecpar->codec_id; + if (stream_in->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + retcd = movie_passthru_streams_video(movie, stream_in); + } else if (stream_in->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + retcd = movie_passthru_streams_audio(movie, stream_in); + } + if (retcd < 0) { + pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); + return retcd; + } + } + pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); + + return 0; + #else + /* This is disabled in the check_passthrough but we need it here for compiling */ + MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("Pass-through disabled. ffmpeg too old")); + return -1; + #endif +} + +static int movie_passthru_check(struct ctx_movie *movie) +{ + if ((movie->netcam_data->status == NETCAM_NOTCONNECTED ) || + (movie->netcam_data->status == NETCAM_RECONNECTING ) ){ + MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO + ,_("rtsp camera not ready for pass-through.")); + return -1; + } if (movie->netcam_data == NULL){ MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("RTSP context not available.")); return -1; } - pthread_mutex_lock(&movie->netcam_data->mutex_transfer); + movie_passthru_reset(movie); - if ((movie->netcam_data->status == NETCAM_NOTCONNECTED ) || - (movie->netcam_data->status == NETCAM_RECONNECTING ) ){ - MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO - ,_("rtsp camera not ready for pass-through.")); - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - return -1; - } + return 0; +} +static int movie_passthru_open(struct ctx_movie *movie) +{ + int retcd; + + retcd = movie_passthru_check(movie); + if (retcd < 0) { + return retcd; + } + + movie->oc = avformat_alloc_context(); + if (!movie->oc) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not allocate output context")); + movie_free_context(movie); + return -1; + } + + /* if (mystrne(movie->codec_name, "mp4")){ MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO ,_("pass-through mode enabled. Changing to MP4 container.")); movie->codec_name = "mp4"; } + */ - retcd = movie_get_oformat(movie); - if (retcd < 0 ) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get codec!")); - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - return -1; - } + retcd = movie_get_oformat(movie); + if (retcd < 0 ) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get output format!")); + return -1; + } - #if (MYFFVER >= 57041) - stream_in = movie->netcam_data->transfer_format->streams[0]; - movie->oc->oformat->video_codec = stream_in->codecpar->codec_id; + retcd = movie_passthru_streams(movie); + if (retcd < 0 ) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get streams!")); + return -1; + } - movie->video_st = avformat_new_stream(movie->oc, NULL); - if (!movie->video_st) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc stream")); - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - return -1; - } + retcd = movie_set_outputfile(movie); + if (retcd < 0){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not set the output file")); + return -1; + } - retcd = avcodec_parameters_copy(movie->video_st->codecpar, stream_in->codecpar); - if (retcd < 0){ - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Unable to copy codec parameters")); - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - return -1; - } - movie->video_st->codecpar->codec_tag = 0; + MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO + , _("Timebase after open audio: %d/%d video: %d/%d") + , movie->strm_audio->time_base.num + , movie->strm_audio->time_base.den + , movie->strm_video->time_base.num + , movie->strm_video->time_base.den); - #elif (MYFFVER >= 55000) - - stream_in = movie->netcam_data->transfer_format->streams[0]; - - movie->video_st = avformat_new_stream(movie->oc, stream_in->codec->codec); - if (!movie->video_st) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not alloc stream")); - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - return -1; - } - - retcd = avcodec_copy_context(movie->video_st->codec, stream_in->codec); - if (retcd < 0){ - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Unable to copy codec parameters")); - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - return -1; - } - movie->video_st->codec->flags |= MY_CODEC_FLAG_GLOBAL_HEADER; - movie->video_st->codec->codec_tag = 0; - #else - /* This is disabled in the util_check_passthrough but we need it here for compiling */ - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); - MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, _("Pass-through disabled. ffmpeg too old")); - return -1; - #endif - - movie->video_st->time_base = stream_in->time_base; - pthread_mutex_unlock(&movie->netcam_data->mutex_transfer); MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO, "Pass-through stream opened"); - return 0; + return 0; } void movie_avcodec_log(void *ignoreme, int errno_flag, const char *fmt, va_list vl) @@ -1296,9 +1356,18 @@ void movie_global_deinit(void) int movie_open(struct ctx_movie *movie) { - int retcd; + if (movie->passthrough) { + retcd = movie_passthru_open(movie); + if (retcd < 0 ) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not setup passthrough!")); + movie_free_context(movie); + return -1; + } + return 0; + } + movie->oc = avformat_alloc_context(); if (!movie->oc) { MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not allocate output context")); @@ -1306,41 +1375,29 @@ int movie_open(struct ctx_movie *movie) return -1; } - if (movie->passthrough) { - retcd = movie_passthru_codec(movie); - if (retcd < 0 ) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not setup passthru!")); - movie_free_context(movie); - return -1; - } + retcd = movie_get_oformat(movie); + if (retcd < 0 ) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get codec!")); + movie_free_context(movie); + return -1; + } - movie_passthru_reset(movie); + retcd = movie_set_codec(movie); + if (retcd < 0 ) { + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Failed to allocate codec!")); + return -1; + } - } else { - retcd = movie_get_oformat(movie); - if (retcd < 0 ) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not get codec!")); - movie_free_context(movie); - return -1; - } + retcd = movie_set_stream(movie); + if (retcd < 0){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not set the stream")); + return -1; + } - retcd = movie_set_codec(movie); - if (retcd < 0 ) { - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Failed to allocate codec!")); - return -1; - } - - retcd = movie_set_stream(movie); - if (retcd < 0){ - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not set the stream")); - return -1; - } - - retcd = movie_set_picture(movie); - if (retcd < 0){ - MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not set the stream")); - return -1; - } + retcd = movie_set_picture(movie); + if (retcd < 0){ + MOTION_LOG(ERR, TYPE_ENCODER, NO_ERRNO, _("Could not set the stream")); + return -1; } retcd = movie_set_outputfile(movie); @@ -1436,7 +1493,7 @@ int movie_put_image(struct ctx_movie *movie, struct ctx_image_data *img_data, co void movie_reset_start_time(struct ctx_movie *movie, const struct timespec *ts1) { - int64_t one_frame_interval = av_rescale_q(1,(AVRational){1, movie->fps},movie->video_st->time_base); + int64_t one_frame_interval = av_rescale_q(1,(AVRational){1, movie->fps}, movie->strm_video->time_base); if (one_frame_interval <= 0) one_frame_interval = 1; movie->base_pts = movie->last_pts + one_frame_interval; diff --git a/src/movie.hpp b/src/movie.hpp index 978e6e8b..3eeb569f 100644 --- a/src/movie.hpp +++ b/src/movie.hpp @@ -47,7 +47,8 @@ enum USER_CODEC { struct ctx_movie { AVFormatContext *oc; - AVStream *video_st; + AVStream *strm_video; + AVStream *strm_audio; AVCodecContext *ctx_codec; AVCodec *codec; AVPacket pkt; diff --git a/src/netcam.cpp b/src/netcam.cpp index eca32001..22a3ba97 100644 --- a/src/netcam.cpp +++ b/src/netcam.cpp @@ -366,7 +366,7 @@ static void netcam_pktarray_resize(struct ctx_cam *cam, int is_highres) /* The 30 is arbitrary */ /* Double the size plus double last diff so we don't catch our tail */ - newsize =((idnbr_first - idnbr_last) * 2 ) + ((netcam->idnbr - idnbr_last ) * 2); + newsize =((idnbr_first - idnbr_last) * 1 ) + ((netcam->idnbr - idnbr_last ) * 2); if (newsize < 30) newsize = 30; pthread_mutex_lock(&netcam->mutex_pktarray); @@ -441,8 +441,8 @@ static void netcam_pktarray_add(struct ctx_netcam *netcam) netcam->pktarray[indx_next].iskey = FALSE; } netcam->pktarray[indx_next].iswritten = FALSE; - netcam->pktarray[indx_next].timestamp_ts.tv_sec = netcam->img_recv->image_time.tv_sec; - netcam->pktarray[indx_next].timestamp_ts.tv_nsec = netcam->img_recv->image_time.tv_nsec; + clock_gettime(CLOCK_REALTIME, &netcam->pktarray[indx_next].timestamp_ts); + netcam->pktarray_index = indx_next; pthread_mutex_unlock(&netcam->mutex_pktarray); @@ -619,6 +619,12 @@ static int netcam_decode_packet(struct ctx_netcam *netcam) if (netcam->finish) return -1; /* This just speeds up the shutdown time */ + if (netcam->packet_recv.stream_index == netcam->audio_stream_index) { + MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO + ,_("%s: Error decoding video packet...it is audio") + ,netcam->cameratype); + } + retcd = netcam_decode_video(netcam); if (retcd <= 0) return retcd; @@ -867,6 +873,14 @@ static int netcam_open_codec(struct ctx_netcam *netcam) netcam_hwdecoders(netcam); + retcd = av_find_best_stream(netcam->format_context + , AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); + if ((retcd < 0) || (netcam->interrupted)){ + netcam_decoder_error(netcam, retcd, "Audio av_find_best_stream"); + return -1; + } + netcam->audio_stream_index = retcd; + netcam->decoder = NULL; retcd = av_find_best_stream(netcam->format_context , AVMEDIA_TYPE_VIDEO, -1, -1, &netcam->decoder, 0); @@ -1192,10 +1206,14 @@ static int netcam_read_image(struct ctx_netcam *netcam) return -1; } else { errcnt = 0; - if (netcam->packet_recv.stream_index == netcam->video_stream_index){ + if ((netcam->packet_recv.stream_index == netcam->video_stream_index) || + (netcam->packet_recv.stream_index == netcam->audio_stream_index)) { /* For a high resolution pass-through we don't decode the image */ - if (netcam->high_resolution && netcam->passthrough){ - if (netcam->packet_recv.data != NULL) size_decoded = 1; + if ((netcam->high_resolution && netcam->passthrough) || + (netcam->packet_recv.stream_index != netcam->video_stream_index)) { + if (netcam->packet_recv.data != NULL) { + size_decoded = 1; + } } else { size_decoded = netcam_decode_packet(netcam); } @@ -1217,13 +1235,17 @@ static int netcam_read_image(struct ctx_netcam *netcam) } clock_gettime(CLOCK_REALTIME, &netcam->img_recv->image_time); - if (!netcam->first_image) netcam->status = NETCAM_CONNECTED; + if (!netcam->first_image) { + netcam->status = NETCAM_CONNECTED; + } /* Skip resize/pix format for high pass-through */ - if (!(netcam->high_resolution && netcam->passthrough)){ + if (!(netcam->high_resolution && netcam->passthrough) && + (netcam->packet_recv.stream_index == netcam->video_stream_index)) { + if ((netcam->imgsize.width != netcam->frame->width) || (netcam->imgsize.height != netcam->frame->height) || - (netcam_check_pixfmt(netcam) != 0) ){ + (netcam_check_pixfmt(netcam) != 0)) { if (netcam_resize(netcam) < 0){ mypacket_unref(netcam->packet_recv); netcam_close_context(netcam); @@ -1235,7 +1257,8 @@ static int netcam_read_image(struct ctx_netcam *netcam) pthread_mutex_lock(&netcam->mutex); netcam->idnbr++; if (netcam->passthrough) netcam_pktarray_add(netcam); - if (!(netcam->high_resolution && netcam->passthrough)) { + if (!(netcam->high_resolution && netcam->passthrough) && + (netcam->packet_recv.stream_index == netcam->video_stream_index)) { xchg = netcam->img_latest; netcam->img_latest = netcam->img_recv; netcam->img_recv = xchg; @@ -1311,7 +1334,7 @@ static void netcam_set_options(struct ctx_netcam *netcam) MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO,_("%s: Setting rtsp/rtmp") ,netcam->cameratype); util_parms_add_default(netcam->params,"rtsp_transport","tcp"); - util_parms_add_default(netcam->params,"allowed_media_types", "video"); + //util_parms_add_default(netcam->params,"allowed_media_types", "video"); } else if (mystreq(netcam->service, "http")) { MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO @@ -1554,43 +1577,29 @@ static int netcam_copy_stream(struct ctx_netcam *netcam) /* Make a static copy of the stream information for use in passthrough processing */ #if (MYFFVER >= 57041) AVStream *transfer_stream, *stream_in; - int retcd; + int retcd, indx; pthread_mutex_lock(&netcam->mutex_transfer); - if (netcam->transfer_format != NULL) avformat_close_input(&netcam->transfer_format); - netcam->transfer_format = avformat_alloc_context(); - transfer_stream = avformat_new_stream(netcam->transfer_format, NULL); - stream_in = netcam->format_context->streams[netcam->video_stream_index]; - retcd = avcodec_parameters_copy(transfer_stream->codecpar, stream_in->codecpar); - if (retcd < 0){ - MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO - ,_("%s: Unable to copy codec parameters") - , netcam->cameratype); - pthread_mutex_unlock(&netcam->mutex_transfer); - return -1; + if (netcam->transfer_format != NULL) { + avformat_close_input(&netcam->transfer_format); } - transfer_stream->time_base = stream_in->time_base; - pthread_mutex_unlock(&netcam->mutex_transfer); - - MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, _("Stream copied for pass-through")); - return 0; - #elif (MYFFVER >= 55000) - - AVStream *transfer_stream, *stream_in; - int retcd; - - pthread_mutex_lock(&netcam->mutex_transfer); - if (netcam->transfer_format != NULL) avformat_close_input(&netcam->transfer_format); netcam->transfer_format = avformat_alloc_context(); - transfer_stream = avformat_new_stream(netcam->transfer_format, NULL); - stream_in = netcam->format_context->streams[netcam->video_stream_index]; - retcd = avcodec_copy_context(transfer_stream->codec, stream_in->codec); - if (retcd < 0){ - MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO, _("Unable to copy codec parameters")); - pthread_mutex_unlock(&netcam->mutex_transfer); - return -1; + for (indx = 0; indx < (int)netcam->format_context->nb_streams; indx++) { + if ((netcam->audio_stream_index == indx) || + (netcam->video_stream_index == indx)) { + transfer_stream = avformat_new_stream(netcam->transfer_format, NULL); + stream_in = netcam->format_context->streams[indx]; + retcd = avcodec_parameters_copy(transfer_stream->codecpar, stream_in->codecpar); + if (retcd < 0){ + MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO + ,_("%s: Unable to copy codec parameters") + , netcam->cameratype); + pthread_mutex_unlock(&netcam->mutex_transfer); + return -1; + } + transfer_stream->time_base = stream_in->time_base; + } } - transfer_stream->time_base = stream_in->time_base; pthread_mutex_unlock(&netcam->mutex_transfer); MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO, _("Stream copied for pass-through")); diff --git a/src/netcam.hpp b/src/netcam.hpp index de6d028c..c7573da8 100644 --- a/src/netcam.hpp +++ b/src/netcam.hpp @@ -105,6 +105,8 @@ struct ctx_netcam { AVDictionary *opts; /* AVOptions when opening the format context */ int swsframe_size; /* The size of the image after resizing */ int video_stream_index; /* Stream index associated with video from camera */ + int audio_stream_index; /* Stream index associated with video from camera */ + enum AVHWDeviceType hw_type; enum AVPixelFormat hw_pix_fmt; AVBufferRef *hw_device_ctx; diff --git a/src/util.cpp b/src/util.cpp index 2419a4b5..83a9601d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -532,17 +532,18 @@ void mythreadname_get(char *threadname) int mycheck_passthrough(struct ctx_cam *cam) { - #if (MYFFVER < 55000) - if (cam->movie_passthrough) + #if (MYFFVER >= 57041) + if (cam->movie_passthrough) { + return true; + } else { + return false; + } + #else + 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){ - return 1; - } else { - return 0; } + return 0; #endif }