mirror of
https://github.com/Motion-Project/motion.git
synced 2026-04-30 10:55:01 -04:00
Improve timing on pass through
This commit is contained in:
112
src/movie.cpp
112
src/movie.cpp
@@ -1010,23 +1010,33 @@ static void movie_passthru_reset(struct ctx_movie *movie)
|
||||
|
||||
static int movie_passthru_pktpts(struct ctx_movie *movie)
|
||||
{
|
||||
int64_t ts_interval;
|
||||
int64_t ts_interval, base_pdts;
|
||||
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;
|
||||
base_pdts = movie->pass_audio_base;
|
||||
} else {
|
||||
tmpbase = movie->strm_video->time_base;
|
||||
indx = movie->netcam_data->video_stream_index;
|
||||
base_pdts = movie->pass_video_base;
|
||||
}
|
||||
|
||||
ts_interval = movie->pkt->pts;
|
||||
if (movie->pkt->pts < base_pdts) {
|
||||
ts_interval = 0;
|
||||
} else {
|
||||
ts_interval = movie->pkt->pts - base_pdts;
|
||||
}
|
||||
movie->pkt->pts = av_rescale_q(ts_interval
|
||||
, movie->netcam_data->transfer_format->streams[indx]->time_base, tmpbase);
|
||||
|
||||
ts_interval = movie->pkt->dts;
|
||||
if (movie->pkt->dts < base_pdts) {
|
||||
ts_interval = 0;
|
||||
} else {
|
||||
ts_interval = movie->pkt->dts - base_pdts;
|
||||
}
|
||||
movie->pkt->dts = av_rescale_q(ts_interval
|
||||
, movie->netcam_data->transfer_format->streams[indx]->time_base, tmpbase);
|
||||
|
||||
@@ -1034,6 +1044,15 @@ static int movie_passthru_pktpts(struct ctx_movie *movie)
|
||||
movie->pkt->duration = av_rescale_q(ts_interval
|
||||
, movie->netcam_data->transfer_format->streams[indx]->time_base, tmpbase);
|
||||
|
||||
/*
|
||||
MOTION_LOG(INF, TYPE_ENCODER, NO_ERRNO
|
||||
,_("base PTS %" PRId64 " new PTS %" PRId64 " srcbase %d-%d newbase %d-%d")
|
||||
,ts_interval, movie->pkt->duration
|
||||
,movie->netcam_data->transfer_format->streams[indx]->time_base.num
|
||||
,movie->netcam_data->transfer_format->streams[indx]->time_base.den
|
||||
,tmpbase.num, tmpbase.den);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1071,10 +1090,60 @@ static void movie_passthru_write(struct ctx_movie *movie, int indx)
|
||||
|
||||
}
|
||||
|
||||
static void movie_passthru_minpts(struct ctx_movie *movie)
|
||||
{
|
||||
|
||||
int indx, indx_audio, indx_video;
|
||||
|
||||
movie->pass_audio_base = 0;
|
||||
movie->pass_video_base = 0;
|
||||
|
||||
pthread_mutex_lock(&movie->netcam_data->mutex_pktarray);
|
||||
indx_audio = movie->netcam_data->audio_stream_index;
|
||||
indx_video = movie->netcam_data->video_stream_index;
|
||||
|
||||
for (indx = 0; indx < movie->netcam_data->pktarray_size; indx++) {
|
||||
if (movie->netcam_data->pktarray[indx].packet->stream_index == indx_audio) {
|
||||
movie->pass_audio_base = movie->netcam_data->pktarray[indx].packet->pts;
|
||||
};
|
||||
if (movie->netcam_data->pktarray[indx].packet->stream_index == indx_video) {
|
||||
movie->pass_video_base = movie->netcam_data->pktarray[indx].packet->pts;
|
||||
};
|
||||
}
|
||||
for (indx = 0; indx < movie->netcam_data->pktarray_size; indx++) {
|
||||
if ((movie->netcam_data->pktarray[indx].packet->stream_index == indx_audio) &&
|
||||
(movie->netcam_data->pktarray[indx].packet->pts < movie->pass_audio_base)) {
|
||||
movie->pass_audio_base = movie->netcam_data->pktarray[indx].packet->pts;
|
||||
};
|
||||
if ((movie->netcam_data->pktarray[indx].packet->stream_index == indx_audio) &&
|
||||
(movie->netcam_data->pktarray[indx].packet->dts < movie->pass_audio_base)) {
|
||||
movie->pass_audio_base = movie->netcam_data->pktarray[indx].packet->dts;
|
||||
};
|
||||
if ((movie->netcam_data->pktarray[indx].packet->stream_index == indx_video) &&
|
||||
(movie->netcam_data->pktarray[indx].packet->pts < movie->pass_video_base)) {
|
||||
movie->pass_video_base = movie->netcam_data->pktarray[indx].packet->pts;
|
||||
};
|
||||
if ((movie->netcam_data->pktarray[indx].packet->stream_index == indx_video) &&
|
||||
(movie->netcam_data->pktarray[indx].packet->dts < movie->pass_video_base)) {
|
||||
movie->pass_video_base = movie->netcam_data->pktarray[indx].packet->dts;
|
||||
};
|
||||
}
|
||||
pthread_mutex_unlock(&movie->netcam_data->mutex_pktarray);
|
||||
|
||||
if (movie->pass_audio_base < 0) {
|
||||
movie->pass_audio_base = 0;
|
||||
}
|
||||
|
||||
if (movie->pass_video_base < 0) {
|
||||
movie->pass_video_base = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
int indx, indx_lastwritten, indx_firstkey, indx_video;
|
||||
|
||||
if (movie->netcam_data == NULL) {
|
||||
return -1;
|
||||
@@ -1097,19 +1166,23 @@ static int movie_passthru_put(struct ctx_movie *movie, struct ctx_image_data *im
|
||||
idnbr_stop = 0;
|
||||
indx_lastwritten = -1;
|
||||
indx_firstkey = -1;
|
||||
indx_video = movie->netcam_data->video_stream_index;
|
||||
|
||||
for(indx = 0; indx < movie->netcam_data->pktarray_size; indx++) {
|
||||
if ((movie->netcam_data->pktarray[indx].iswritten) &&
|
||||
(movie->netcam_data->pktarray[indx].idnbr > idnbr_lastwritten)) {
|
||||
(movie->netcam_data->pktarray[indx].idnbr > idnbr_lastwritten) &&
|
||||
(movie->netcam_data->pktarray[indx].packet->stream_index == indx_video)) {
|
||||
idnbr_lastwritten=movie->netcam_data->pktarray[indx].idnbr;
|
||||
indx_lastwritten = indx;
|
||||
}
|
||||
if ((movie->netcam_data->pktarray[indx].idnbr > idnbr_stop) &&
|
||||
(movie->netcam_data->pktarray[indx].idnbr <= idnbr_image)) {
|
||||
(movie->netcam_data->pktarray[indx].idnbr <= idnbr_image)&&
|
||||
(movie->netcam_data->pktarray[indx].packet->stream_index == indx_video)) {
|
||||
idnbr_stop=movie->netcam_data->pktarray[indx].idnbr;
|
||||
}
|
||||
if ((movie->netcam_data->pktarray[indx].iskey) &&
|
||||
(movie->netcam_data->pktarray[indx].idnbr <= idnbr_firstkey)) {
|
||||
(movie->netcam_data->pktarray[indx].idnbr <= idnbr_firstkey)&&
|
||||
(movie->netcam_data->pktarray[indx].packet->stream_index == indx_video)) {
|
||||
idnbr_firstkey=movie->netcam_data->pktarray[indx].idnbr;
|
||||
indx_firstkey = indx;
|
||||
}
|
||||
@@ -1149,7 +1222,7 @@ static int movie_passthru_put(struct ctx_movie *movie, struct ctx_image_data *im
|
||||
|
||||
static int movie_passthru_streams_video(struct ctx_movie *movie, AVStream *stream_in)
|
||||
{
|
||||
int retcd;
|
||||
int retcd;
|
||||
|
||||
movie->strm_video = avformat_new_stream(movie->oc, NULL);
|
||||
if (!movie->strm_video) {
|
||||
@@ -1165,11 +1238,14 @@ static int movie_passthru_streams_video(struct ctx_movie *movie, AVStream *strea
|
||||
|
||||
movie->strm_video->codecpar->codec_tag = 0;
|
||||
movie->strm_video->time_base = stream_in->time_base;
|
||||
movie->strm_video->avg_frame_rate = stream_in->avg_frame_rate;
|
||||
|
||||
MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO
|
||||
, _("video timebase %d/%d")
|
||||
, _("video timebase %d/%d fps %d/%d")
|
||||
, movie->strm_video->time_base.num
|
||||
, movie->strm_video->time_base.den);
|
||||
, movie->strm_video->time_base.den
|
||||
, movie->strm_video->avg_frame_rate.num
|
||||
, movie->strm_video->avg_frame_rate.den);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1196,6 +1272,7 @@ static int movie_passthru_streams_audio(struct ctx_movie *movie, AVStream *strea
|
||||
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;
|
||||
movie->strm_audio->avg_frame_rate = stream_in->avg_frame_rate;
|
||||
|
||||
MOTION_LOG(DBG, TYPE_ENCODER, NO_ERRNO
|
||||
, _("audio timebase %d/%d")
|
||||
@@ -1269,13 +1346,13 @@ static int movie_passthru_open(struct ctx_movie *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";
|
||||
}
|
||||
*/
|
||||
if (mystrne(movie->codec_name, "mp4") && mystrne(movie->codec_name, "mkv")) {
|
||||
MOTION_LOG(NTC, TYPE_ENCODER, NO_ERRNO
|
||||
,_("Changing to MP4 container for pass-through."));
|
||||
movie->codec_name = "mp4";
|
||||
}
|
||||
|
||||
movie_passthru_minpts(movie);
|
||||
|
||||
retcd = movie_get_oformat(movie);
|
||||
if (retcd < 0 ) {
|
||||
@@ -1502,7 +1579,6 @@ void movie_close(struct ctx_movie *movie)
|
||||
|
||||
}
|
||||
|
||||
|
||||
int movie_put_image(struct ctx_movie *movie, struct ctx_image_data *img_data, const struct timespec *ts1)
|
||||
{
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ struct ctx_movie {
|
||||
const char *codec_name;
|
||||
int64_t last_pts;
|
||||
int64_t base_pts;
|
||||
int64_t pass_audio_base;
|
||||
int64_t pass_video_base;
|
||||
bool test_mode;
|
||||
int gop_cnt;
|
||||
struct timespec start_time;
|
||||
|
||||
@@ -1277,6 +1277,7 @@ static int netcam_read_image(struct ctx_netcam *netcam)
|
||||
}
|
||||
}
|
||||
clock_gettime(CLOCK_REALTIME, &netcam->img_recv->image_time);
|
||||
netcam->last_stream_index = netcam->packet_recv->stream_index;
|
||||
|
||||
if (!netcam->first_image) {
|
||||
netcam->status = NETCAM_CONNECTED;
|
||||
@@ -1546,6 +1547,9 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam )
|
||||
netcam->reconnect_count = 0;
|
||||
netcam->src_fps = -1; /* Default to neg so we know it has not been set */
|
||||
netcam->capture_rate = -1;
|
||||
netcam->video_stream_index = -1;
|
||||
netcam->audio_stream_index = -1;
|
||||
netcam->last_stream_index = -1;
|
||||
|
||||
for (indx = 0; indx < netcam->params->params_count; indx++) {
|
||||
if (mystreq(netcam->params->params_array[indx].param_name,"decoder")) {
|
||||
@@ -1648,6 +1652,7 @@ static int netcam_copy_stream(struct ctx_netcam *netcam)
|
||||
return -1;
|
||||
}
|
||||
transfer_stream->time_base = stream_in->time_base;
|
||||
transfer_stream->avg_frame_rate = stream_in->avg_frame_rate;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&netcam->mutex_transfer);
|
||||
@@ -1849,6 +1854,19 @@ static int netcam_connect(struct ctx_netcam *netcam)
|
||||
, _("%s: Capture FPS should be greater than camera FPS.")
|
||||
, netcam->cameratype);
|
||||
}
|
||||
|
||||
if (netcam->audio_stream_index != -1) {
|
||||
/* The following is not technically precise but we want to convey in simple terms
|
||||
* that the capture rate must go faster to account for the additional packets read
|
||||
* for the audio stream. The technically correct process is that our wait timer in
|
||||
* the handler is only triggered when the last packet is a video stream
|
||||
*/
|
||||
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO
|
||||
,_("%s: An audio stream was detected. Capture_rate increased to compensate.")
|
||||
,netcam->cameratype);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1985,7 +2003,9 @@ static void *netcam_handler(void *arg)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
netcam_handler_wait(netcam);
|
||||
if (netcam->last_stream_index == netcam->video_stream_index) {
|
||||
netcam_handler_wait(netcam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ struct ctx_netcam {
|
||||
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 */
|
||||
int last_stream_index; /* Index of the last packet read */
|
||||
|
||||
enum AVHWDeviceType hw_type;
|
||||
enum AVPixelFormat hw_pix_fmt;
|
||||
|
||||
Reference in New Issue
Block a user