Merge branch 'master' of github.com:ZoneMinder/ZoneMinder

This commit is contained in:
Isaac Connor 2019-09-12 16:53:16 -04:00
commit 332fd80cf8
5 changed files with 183 additions and 279 deletions

View File

@ -289,9 +289,10 @@ static void zm_log_fps(double d, const char *postfix) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
void zm_dump_codecpar ( const AVCodecParameters *par ) { void zm_dump_codecpar ( const AVCodecParameters *par ) {
Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d) codec_tag(%d) width(%d) height(%d) bit_rate(%d) format(%d = %s)", Debug(1, "Dumping codecpar codec_type(%d) codec_id(%d %s) codec_tag(%d) width(%d) height(%d) bit_rate(%d) format(%d = %s)",
par->codec_type, par->codec_type,
par->codec_id, par->codec_id,
avcodec_get_name(par->codec_id),
par->codec_tag, par->codec_tag,
par->width, par->width,
par->height, par->height,
@ -303,10 +304,11 @@ void zm_dump_codecpar ( const AVCodecParameters *par ) {
#endif #endif
void zm_dump_codec(const AVCodecContext *codec) { void zm_dump_codec(const AVCodecContext *codec) {
Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d) width(%d) height(%d) timebase(%d/%d) format(%s)\n" Debug(1, "Dumping codec_context codec_type(%d) codec_id(%d %s) width(%d) height(%d) timebase(%d/%d) format(%s) "
"gop_size %d max_b_frames %d me_cmp %d me_range %d qmin %d qmax %d", "gop_size %d max_b_frames %d me_cmp %d me_range %d qmin %d qmax %d",
codec->codec_type, codec->codec_type,
codec->codec_id, codec->codec_id,
avcodec_get_name(codec->codec_id),
codec->width, codec->width,
codec->height, codec->height,
codec->time_base.num, codec->time_base.num,
@ -327,7 +329,6 @@ void zm_dump_codec(const AVCodecContext *codec) {
/* "user interface" functions */ /* "user interface" functions */
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) { void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output) {
char buf[256];
Debug(1, "Dumping stream index i(%d) index(%d)", i, index ); Debug(1, "Dumping stream index i(%d) index(%d)", i, index );
int flags = (is_output ? ic->oformat->flags : ic->iformat->flags); int flags = (is_output ? ic->oformat->flags : ic->iformat->flags);
AVStream *st = ic->streams[i]; AVStream *st = ic->streams[i];
@ -350,8 +351,14 @@ void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output)
st->codec_info_nb_frames, codec->frame_size, st->codec_info_nb_frames, codec->frame_size,
st->time_base.num, st->time_base.den st->time_base.num, st->time_base.den
); );
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
Debug(1, "codec: %s", avcodec_get_name(st->codecpar->codec_id));
#else
char buf[256];
avcodec_string(buf, sizeof(buf), st->codec, is_output); avcodec_string(buf, sizeof(buf), st->codec, is_output);
Debug(1, "codec: %s", buf); Debug(1, "codec: %s", buf);
#endif
if ( st->sample_aspect_ratio.num && // default if ( st->sample_aspect_ratio.num && // default
av_cmp_q(st->sample_aspect_ratio, codec->sample_aspect_ratio) av_cmp_q(st->sample_aspect_ratio, codec->sample_aspect_ratio)
@ -477,6 +484,27 @@ bool is_audio_context( AVCodecContext *codec_context ) {
#endif #endif
} }
int zm_receive_packet(AVCodecContext *context, AVPacket &packet) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
int ret = avcodec_receive_packet(context, &packet);
if ( ret < 0 ) {
if ( AVERROR_EOF != ret ) {
Error("Error encoding (%d) (%s)", ret,
av_err2str(ret));
}
return 0;
}
return 1;
#else
int got_packet = 0;
int ret = avcodec_encode_audio2(context, &packet, NULL, &got_packet);
if ( ret < 0 ) {
Error("Error encoding (%d) (%s)", ret, av_err2str(ret));
}
return got_packet;
#endif
} // end int zm_receive_packet(AVCodecContext *context, AVPacket &packet)
int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet) { int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet) {
int ret; int ret;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
@ -600,3 +628,10 @@ void dumpPacket(AVPacket *pkt, const char *text) {
pkt->duration); pkt->duration);
Debug(2, "%s:%d:%s: %s", __FILE__, __LINE__, text, b); Debug(2, "%s:%d:%s: %s", __FILE__, __LINE__, text, b);
} }
void zm_packet_copy_rescale_ts(const AVPacket *ipkt, AVPacket *opkt, const AVRational src_tb, const AVRational dst_tb) {
opkt->pts = ipkt->pts;
opkt->dts = ipkt->dts;
opkt->duration = ipkt->duration;
av_packet_rescale_ts(opkt, src_tb, dst_tb);
}

View File

@ -352,9 +352,12 @@ bool is_audio_stream(AVStream *);
bool is_video_context(AVCodec *); bool is_video_context(AVCodec *);
bool is_audio_context(AVCodec *); bool is_audio_context(AVCodec *);
int zm_receive_packet(AVCodecContext *context, AVPacket &packet);
int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet); int zm_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
int zm_send_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet); int zm_send_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
void dumpPacket(AVStream *, AVPacket *,const char *text=""); void dumpPacket(AVStream *, AVPacket *,const char *text="");
void dumpPacket(AVPacket *,const char *text=""); void dumpPacket(AVPacket *,const char *text="");
void zm_packet_copy_rescale_ts(const AVPacket *ipkt, AVPacket *opkt, const AVRational src_tb, const AVRational dst_tb);
#endif // ZM_FFMPEG_H #endif // ZM_FFMPEG_H

View File

@ -193,18 +193,6 @@ VideoStore::VideoStore(
); );
video_out_stream->r_frame_rate = video_in_stream->r_frame_rate; video_out_stream->r_frame_rate = video_in_stream->r_frame_rate;
} }
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_out_ctx);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
return;
} else {
zm_dump_codec(video_out_ctx);
}
zm_dump_codecpar(video_in_stream->codecpar);
zm_dump_codecpar(video_out_stream->codecpar);
#endif
Debug(3, Debug(3,
"Time bases: VIDEO in stream (%d/%d) in codec: (%d/%d) out " "Time bases: VIDEO in stream (%d/%d) in codec: (%d/%d) out "
"stream: (%d/%d) out codec (%d/%d)", "stream: (%d/%d) out codec (%d/%d)",
@ -222,6 +210,10 @@ VideoStore::VideoStore(
} }
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
/* I'm not entirely sure that this is a good idea. We may have to do it someday but really only when transcoding
* * think what I was trying to achieve here was to have zm_dump_codecpar output nice info
* */
#if 0
AVDictionary *opts = 0; AVDictionary *opts = 0;
if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) { if ( (ret = avcodec_open2(video_out_ctx, video_out_codec, &opts)) < 0 ) {
Warning("Can't open video codec (%s) %s", Warning("Can't open video codec (%s) %s",
@ -235,6 +227,24 @@ VideoStore::VideoStore(
while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) { while ( (e = av_dict_get(opts, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL ) {
Warning("Encoder Option %s not recognized by ffmpeg codec", e->key); Warning("Encoder Option %s not recognized by ffmpeg codec", e->key);
} }
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_out_ctx);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
return;
} else {
zm_dump_codec(video_out_ctx);
}
#else
ret = avcodec_parameters_from_context(video_out_stream->codecpar, video_in_ctx);
if ( ret < 0 ) {
Error("Could not initialize video_out_ctx parameters");
return;
} else {
zm_dump_codec(video_out_ctx);
}
#endif
zm_dump_codecpar(video_in_stream->codecpar);
zm_dump_codecpar(video_out_stream->codecpar);
#endif #endif
Monitor::Orientation orientation = monitor->getOrientation(); Monitor::Orientation orientation = monitor->getOrientation();
@ -274,6 +284,7 @@ VideoStore::VideoStore(
audio_first_pts = 0; audio_first_pts = 0;
audio_first_dts = 0; audio_first_dts = 0;
/* When encoding audio, these are used to tell us what the correct pts is, because it gets lost during resampling. */
audio_next_pts = 0; audio_next_pts = 0;
audio_next_dts = 0; audio_next_dts = 0;
@ -419,9 +430,9 @@ bool VideoStore::open() {
VideoStore::~VideoStore() { VideoStore::~VideoStore() {
if ( oc->pb ) { if ( oc->pb ) {
int ret;
if ( audio_out_codec ) { if ( audio_out_codec ) {
// The codec queues data. We need to send a flush command and out // The codec queues data. We need to send a flush command and out
// whatever we get. Failures are not fatal. // whatever we get. Failures are not fatal.
AVPacket pkt; AVPacket pkt;
@ -429,99 +440,53 @@ VideoStore::~VideoStore() {
pkt.data = NULL; pkt.data = NULL;
pkt.size = 0; pkt.size = 0;
av_init_packet(&pkt); av_init_packet(&pkt);
/*
* At the end of the file, we pass the remaining samples to
* the encoder. */
int frame_size = audio_out_ctx->frame_size;
while ( av_audio_fifo_size(fifo) > 0 ) {
/* Take one frame worth of audio samples from the FIFO buffer,
* encode it and write it to the output file. */
Debug(1, "Remaining samples in fifo for AAC codec frame_size %d > fifo size %d",
frame_size, av_audio_fifo_size(fifo));
// SHould probably set the frame size to what is reported FIXME
if ( av_audio_fifo_read(fifo, (void **)out_frame->data, frame_size) ) {
av_init_packet(&opkt);
if ( zm_send_frame(audio_out_ctx, out_frame, opkt) ) {
if ( zm_receive_packet(audio_out_ctx, pkt) )
pkt.stream_index = audio_out_stream->index;
pkt.duration = av_rescale_q(
pkt.duration,
audio_out_ctx->time_base,
audio_out_stream->time_base);
}
} // end if data returned from fifo
} // end while still data in the fifo
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Put encoder into flushing mode // Put encoder into flushing mode
avcodec_send_frame(audio_out_ctx, NULL); avcodec_send_frame(audio_out_ctx, NULL);
#endif #endif
while (1) { while (1) {
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) if ( ! zm_receive_packet(audio_out_ctx, pkt) )
ret = avcodec_receive_packet(audio_out_ctx, &pkt);
if ( ret < 0 ) {
if ( AVERROR_EOF != ret ) {
Error("Error encoding audio while flushing (%d) (%s)", ret,
av_err2str(ret));
}
break; break;
}
#else
int got_packet = 0;
ret = avcodec_encode_audio2(audio_out_ctx, &pkt, NULL, &got_packet);
if ( ret < 0 ) {
Error("Error encoding audio while flushing (%d) (%s)", ret,
av_err2str(ret));
break;
}
Debug(1, "Have audio encoder, need to flush it's out");
if ( !got_packet ) {
break;
}
#endif
dumpPacket(&pkt, "raw from encoder"); dumpPacket(&pkt, "raw from encoder");
// Need to adjust pts and dts and duration
pkt.stream_index = audio_out_stream->index; pkt.stream_index = audio_out_stream->index;
pkt.duration = av_rescale_q( av_packet_rescale_ts(&pkt, audio_out_ctx->time_base, audio_out_stream->time_base);
pkt.duration,
audio_out_ctx->time_base,
audio_out_stream->time_base);
// Scale the PTS of the outgoing packet to be the correct time base
if ( pkt.pts != AV_NOPTS_VALUE ) {
#if 0
pkt.pts = av_rescale_q(
pkt.pts,
audio_out_ctx->time_base,
audio_in_stream->time_base);
// audio_first_pts is in audio_in_stream time base
pkt.pts -= audio_first_pts;
pkt.pts = av_rescale_q(
pkt.pts,
audio_in_stream->time_base,
audio_out_stream->time_base);
#else
pkt.pts = av_rescale_q(
pkt.pts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
#endif
Debug(2, "audio pkt.pts = %" PRId64 " from first_pts(%" PRId64 ")",
pkt.pts, audio_first_pts);
} else {
Debug(2, "pkt.pts = undef");
pkt.pts = AV_NOPTS_VALUE;
}
if ( pkt.dts != AV_NOPTS_VALUE ) {
#if 0
pkt.dts = av_rescale_q(
pkt.dts,
audio_out_ctx->time_base,
audio_in_stream->time_base);
pkt.dts -= audio_first_dts;
pkt.dts = av_rescale_q(
pkt.dts,
audio_in_stream->time_base,
audio_out_stream->time_base);
#else
pkt.dts = av_rescale_q(
pkt.dts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
#endif
Debug(2, "pkt.dts = %" PRId64 " - first_dts(%" PRId64 ")",
pkt.dts, audio_first_dts);
} else {
pkt.dts = AV_NOPTS_VALUE;
}
dumpPacket(audio_out_stream, &pkt, "writing flushed packet"); dumpPacket(audio_out_stream, &pkt, "writing flushed packet");
av_interleaved_write_frame(oc, &pkt); av_interleaved_write_frame(oc, &pkt);
zm_av_packet_unref(&pkt); zm_av_packet_unref(&pkt);
} // while have buffered frames } // while have buffered frames
} // end if audio_out_codec } // end if audio_out_codec
// Flush Queues // Flush Queues
Debug(1,"Flushing interleaved queues"); Debug(1,"Flushing interleaved queues");
@ -711,7 +676,7 @@ bool VideoStore::setup_resampler() {
} }
} }
if ( found ) { if ( found ) {
Debug(3, "Sample rate is good"); Debug(3, "Sample rate is good %d", audio_out_ctx->sample_rate);
} else { } else {
audio_out_ctx->sample_rate = audio_out_ctx->sample_rate =
audio_out_codec->supported_samplerates[0]; audio_out_codec->supported_samplerates[0];
@ -743,6 +708,7 @@ bool VideoStore::setup_resampler() {
audio_out_stream = NULL; audio_out_stream = NULL;
return false; return false;
} }
zm_dump_codec(audio_out_ctx);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
ret = avcodec_parameters_from_context( ret = avcodec_parameters_from_context(
@ -752,6 +718,7 @@ bool VideoStore::setup_resampler() {
return false; return false;
} }
#endif #endif
zm_dump_codecpar(audio_out_stream->codecpar);
Debug(3, Debug(3,
"Time bases: AUDIO in stream (%d/%d) in codec: (%d/%d) out " "Time bases: AUDIO in stream (%d/%d) in codec: (%d/%d) out "
@ -923,6 +890,7 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
); );
if ( duration <= 0 ) { if ( duration <= 0 ) {
// Why are we setting the duration to 1? // Why are we setting the duration to 1?
Warning("Duration is 0, setting to 1");
duration = ipkt->duration ? ipkt->duration : av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base); duration = ipkt->duration ? ipkt->duration : av_rescale_q(1,video_in_stream->time_base, video_out_stream->time_base);
} }
} }
@ -936,17 +904,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.pts = 0; opkt.pts = 0;
Debug(2, "Starting video first_pts will become %" PRId64, ipkt->pts); Debug(2, "Starting video first_pts will become %" PRId64, ipkt->pts);
video_first_pts = ipkt->pts; video_first_pts = ipkt->pts;
#if 1
if ( audio_in_stream ) {
// Since audio starts after the start of the video, need to set this here.
audio_first_pts = av_rescale_q(
ipkt->pts,
video_in_stream->time_base,
audio_in_stream->time_base
);
Debug(2, "Starting audio first_pts will become %" PRId64, audio_first_pts);
}
#endif
} else { } else {
opkt.pts = av_rescale_q( opkt.pts = av_rescale_q(
ipkt->pts - video_first_pts, ipkt->pts - video_first_pts,
@ -960,8 +917,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
} else { } else {
Debug(3, "opkt.pts = undef"); Debug(3, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE; opkt.pts = AV_NOPTS_VALUE;
// can't set 0, it will get rejected
//AV_NOPTS_VALUE;
} }
// Just because the in stream wraps, doesn't mean the out needs to. // Just because the in stream wraps, doesn't mean the out needs to.
// Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out. // Really, if we are limiting ourselves to 10min segments I can't imagine every wrapping in the out.
@ -974,17 +929,6 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt) {
opkt.dts = 0; opkt.dts = 0;
Debug(2, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts); Debug(2, "Starting video first_dts will become (%" PRId64 ")", ipkt->dts);
video_first_dts = ipkt->dts; video_first_dts = ipkt->dts;
#if 1
if ( audio_in_stream ) {
// Since audio starts after the start of the video, need to set this here.
audio_first_dts = av_rescale_q(
ipkt->dts,
video_in_stream->time_base,
audio_in_stream->time_base
);
Debug(2, "Starting audio first dts will become %" PRId64, audio_first_dts);
}
#endif
} else { } else {
opkt.dts = av_rescale_q( opkt.dts = av_rescale_q(
ipkt->dts - video_first_dts, ipkt->dts - video_first_dts,
@ -1035,6 +979,40 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} }
dumpPacket(audio_in_stream, ipkt, "input packet"); dumpPacket(audio_in_stream, ipkt, "input packet");
if ( !audio_first_pts ) {
// Since audio starts after the start of the video, need to set this here.
audio_first_pts = av_rescale_q(
video_first_pts,
video_in_stream->time_base,
audio_in_stream->time_base
);
Debug(2, "Starting audio first_pts will become %" PRId64, audio_first_pts);
audio_next_pts = ipkt->pts - audio_first_pts;
if ( audio_next_pts < 0 ) {
audio_first_pts -= audio_next_pts;
audio_next_pts = 0;
}
}
if ( !audio_first_dts ) {
// Since audio starts after the start of the video, need to set this here.
audio_first_dts = av_rescale_q(
video_first_dts,
video_in_stream->time_base,
audio_in_stream->time_base
);
audio_next_dts = ipkt->dts - audio_first_dts;
if ( ipkt->dts < 0 ) {
audio_first_dts -= ipkt->dts;
ipkt->dts = 0;
}
Debug(2, "Starting audio first_dts will become %" PRId64, audio_first_dts);
}
// Need to adjust pts before feeding to decoder.... should really copy the pkt instead of modifying it
ipkt->pts -= audio_first_pts;
ipkt->dts -= audio_first_dts;
dumpPacket(audio_in_stream, ipkt, "after pts adjustment");
if ( audio_out_codec ) { if ( audio_out_codec ) {
if ( ( ret = zm_receive_frame(audio_in_ctx, in_frame, *ipkt) ) < 0 ) { if ( ( ret = zm_receive_frame(audio_in_ctx, in_frame, *ipkt) ) < 0 ) {
Debug(3, "Not ready to receive frame"); Debug(3, "Not ready to receive frame");
@ -1042,140 +1020,31 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} }
zm_dump_frame(in_frame, "In frame from decode"); zm_dump_frame(in_frame, "In frame from decode");
if ( in_frame->pts != AV_NOPTS_VALUE ) {
if ( !audio_first_pts ) {
audio_first_pts = in_frame->pts;
Debug(1, "No audio_first_pts setting to %" PRId64, audio_first_pts);
in_frame->pts = 0;
} else {
// out_frame_pts is in codec->timebase, audio_first_pts is in packet timebase.
in_frame->pts = in_frame->pts - audio_first_pts;
zm_dump_frame(in_frame, "in frame after pts adjustment");
}
} else {
// sending AV_NOPTS_VALUE doesn't really work but we seem to get it in ffmpeg 2.8
in_frame->pts = audio_next_pts;
}
if ( !resample_audio() ) { if ( !resample_audio() ) {
//av_frame_unref(in_frame); //av_frame_unref(in_frame);
return 0; return 0;
} }
zm_dump_frame(out_frame, "Out frame after resample"); zm_dump_frame(out_frame, "Out frame after resample");
#if 0
// out_frame pts is in the input pkt pts... needs to be adjusted before sending to the encoder
if ( out_frame->pts != AV_NOPTS_VALUE ) {
if ( !audio_first_pts ) {
audio_first_pts = out_frame->pts;
Debug(1, "No audio_first_pts setting to %" PRId64, audio_first_pts);
out_frame->pts = 0;
} else {
// out_frame_pts is in codec->timebase, audio_first_pts is in packet timebase.
out_frame->pts = out_frame->pts - audio_first_pts;
zm_dump_frame(out_frame, "Out frame after pts adjustment");
}
//
} else {
// sending AV_NOPTS_VALUE doesn't really work but we seem to get it in ffmpeg 2.8
out_frame->pts = audio_next_pts;
}
audio_next_pts = out_frame->pts + out_frame->nb_samples;
#endif
av_init_packet(&opkt); av_init_packet(&opkt);
if ( !zm_send_frame(audio_out_ctx, out_frame, opkt) ) { if ( !zm_send_frame(audio_out_ctx, out_frame, opkt) ) {
return 0; return 0;
} }
dumpPacket(audio_out_stream, &opkt, "raw opkt");
Debug(1, "Duration before %d in %d/%d", opkt.duration,
audio_out_ctx->time_base.num,
audio_out_ctx->time_base.den);
opkt.duration = av_rescale_q(
opkt.duration,
audio_out_ctx->time_base,
audio_out_stream->time_base);
Debug(1, "Duration after %d in %d/%d", opkt.duration,
audio_out_stream->time_base.num,
audio_out_stream->time_base.den);
// Scale the PTS of the outgoing packet to be the correct time base // Scale the PTS of the outgoing packet to be the correct time base
#if 0 av_packet_rescale_ts(&opkt,
if ( ipkt->pts != AV_NOPTS_VALUE ) {
if ( !audio_first_pts ) {
opkt.pts = 0;
audio_first_pts = ipkt->pts;
Debug(1, "No audio_first_pts");
} else {
opkt.pts = av_rescale_q(
opkt.pts,
audio_out_ctx->time_base, audio_out_ctx->time_base,
audio_out_stream->time_base); audio_out_stream->time_base);
opkt.pts -= audio_first_pts;
Debug(2, "audio opkt.pts = %" PRId64 " from first_pts %" PRId64,
opkt.pts, audio_first_pts);
}
} else {
Debug(2, "opkt.pts = undef");
opkt.pts = AV_NOPTS_VALUE;
}
if ( opkt.dts != AV_NOPTS_VALUE ) { write_packet(&opkt, audio_out_stream);
if ( !audio_first_dts ) {
opkt.dts = 0;
audio_first_dts = opkt.dts;
} else {
opkt.dts = av_rescale_q(
opkt.dts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
opkt.dts -= audio_first_dts;
Debug(2, "audio opkt.dts = %" PRId64 " from first_dts %" PRId64,
opkt.dts, audio_first_dts);
}
audio_last_dts = opkt.dts;
} else {
opkt.dts = AV_NOPTS_VALUE;
}
#else
opkt.pts = av_rescale_q(
opkt.pts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
opkt.dts = av_rescale_q(
opkt.dts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
#endif
write_packet(&opkt, audio_out_stream);
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0) #if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// While the encoder still has packets for us // While the encoder still has packets for us
while ( !avcodec_receive_packet(audio_out_ctx, &opkt) ) { while ( !avcodec_receive_packet(audio_out_ctx, &opkt) ) {
opkt.pts = av_rescale_q( av_packet_rescale_ts(&opkt, audio_out_ctx->time_base, audio_out_stream->time_base);
opkt.pts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
opkt.dts = av_rescale_q(
opkt.dts,
audio_out_ctx->time_base,
audio_out_stream->time_base);
dumpPacket(audio_out_stream, &opkt, "raw opkt"); dumpPacket(audio_out_stream, &opkt, "raw opkt");
Debug(1, "Duration before %d in %d/%d", opkt.duration,
audio_out_ctx->time_base.num,
audio_out_ctx->time_base.den);
opkt.duration = av_rescale_q(
opkt.duration,
audio_out_ctx->time_base,
audio_out_stream->time_base);
Debug(1, "Duration after %d in %d/%d", opkt.duration,
audio_out_stream->time_base.num,
audio_out_stream->time_base.den);
write_packet(&opkt, audio_out_stream); write_packet(&opkt, audio_out_stream);
} }
#endif #endif
@ -1188,6 +1057,7 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
opkt.size = ipkt->size; opkt.size = ipkt->size;
opkt.flags = ipkt->flags; opkt.flags = ipkt->flags;
#if 0
if ( ipkt->duration && (ipkt->duration != AV_NOPTS_VALUE) ) { if ( ipkt->duration && (ipkt->duration != AV_NOPTS_VALUE) ) {
opkt.duration = av_rescale_q( opkt.duration = av_rescale_q(
ipkt->duration, ipkt->duration,
@ -1229,6 +1099,12 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt) {
} else { } else {
opkt.dts = AV_NOPTS_VALUE; opkt.dts = AV_NOPTS_VALUE;
} }
#else
opkt.duration = ipkt->duration;
opkt.pts = ipkt->pts;
opkt.dts = ipkt->dts;
av_packet_rescale_ts(&opkt, audio_in_stream->time_base, audio_out_stream->time_base);
#endif
write_packet(&opkt, audio_out_stream); write_packet(&opkt, audio_out_stream);
zm_av_packet_unref(&opkt); zm_av_packet_unref(&opkt);
@ -1318,12 +1194,17 @@ int VideoStore::resample_audio() {
zm_dump_frame(out_frame, "Out frame after fifo read"); zm_dump_frame(out_frame, "Out frame after fifo read");
// resampling changes the duration because the timebase is 1/samples // resampling changes the duration because the timebase is 1/samples
// I think we should be dealing in codec timebases not stream // I think we should be dealing in codec timebases not stream
#if 0
if ( in_frame->pts != AV_NOPTS_VALUE ) { if ( in_frame->pts != AV_NOPTS_VALUE ) {
out_frame->pts = av_rescale_q( out_frame->pts = av_rescale_q(
in_frame->pts, in_frame->pts,
audio_in_ctx->time_base, audio_in_ctx->time_base,
audio_out_ctx->time_base); audio_out_ctx->time_base);
} }
#else
out_frame->pts = audio_next_pts;
audio_next_pts += out_frame->nb_samples;
#endif
zm_dump_frame(out_frame, "Out frame after timestamp conversion"); zm_dump_frame(out_frame, "Out frame after timestamp conversion");
#else #else
#if defined(HAVE_LIBAVRESAMPLE) #if defined(HAVE_LIBAVRESAMPLE)

View File

@ -22,14 +22,14 @@ function gotoStep2( element ) {
form.submit(); form.submit();
} }
function configureButtons( element ) { function configureButtons(element) {
var form = element.form; var form = element.form;
if (form.elements.namedItem("nextBtn")) { if (form.elements.namedItem('nextBtn')) {
form.nextBtn.disabled = (form.probe.selectedIndex==0) || form.nextBtn.disabled = (form.probe.selectedIndex==0) ||
(form.username == "") || (form.username == null) || (form.Username == '') || (form.Username == null) ||
(form.password == "") || (form.password == null); (form.Password == '') || (form.Password == null);
} }
if (form.elements.namedItem("saveBtn")) { if (form.elements.namedItem('saveBtn')) {
form.saveBtn.disabled = (form.probe.selectedIndex==0); form.saveBtn.disabled = (form.probe.selectedIndex==0);
} }
} }

View File

@ -41,18 +41,18 @@ function execONVIF( $cmd ) {
Please the following command from a command line for more information:<br/><br/>$shell_command" Please the following command from a command line for more information:<br/><br/>$shell_command"
); );
} else { } else {
ZM\Logger::Debug( "Results from probe: " . implode( '<br/>', $output ) ); ZM\Logger::Debug('Results from probe: '.implode('<br/>', $output));
} }
return $output; return $output;
} }
function probeCameras( $localIp ) { function probeCameras($localIp) {
$cameras = array(); $cameras = array();
if ( $lines = @execONVIF( 'probe' ) ) { if ( $lines = @execONVIF('probe') ) {
foreach ( $lines as $line ) { foreach ( $lines as $line ) {
$line = rtrim( $line ); $line = rtrim($line);
if ( preg_match( '|^(.+),(.+),\s\((.*)\)$|', $line, $matches ) ) { if ( preg_match('|^(.+),(.+),\s\((.*)\)$|', $line, $matches) ) {
$device_ep = $matches[1]; $device_ep = $matches[1];
$soapversion = $matches[2]; $soapversion = $matches[2];
$camera = array( $camera = array(
@ -65,7 +65,7 @@ function probeCameras( $localIp ) {
), ),
); );
foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) { foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) {
if ( preg_match( '|(.+)=\'(.*)\'|', $attr_val, $tokens ) ) { if ( preg_match('|(.+)=\'(.*)\'|', $attr_val, $tokens) ) {
if ( $tokens[1] == 'hardware' ) { if ( $tokens[1] == 'hardware' ) {
$camera['model'] = $tokens[2]; $camera['model'] = $tokens[2];
} elseif ( $tokens[1] == 'name' ) { } elseif ( $tokens[1] == 'name' ) {
@ -84,7 +84,7 @@ function probeCameras( $localIp ) {
return $cameras; return $cameras;
} // end function probeCameras } // end function probeCameras
function probeProfiles( $device_ep, $soapversion, $username, $password ) { function probeProfiles($device_ep, $soapversion, $username, $password) {
$profiles = array(); $profiles = array();
if ( $lines = @execONVIF("profiles $device_ep $soapversion $username $password") ) { if ( $lines = @execONVIF("profiles $device_ep $soapversion $username $password") ) {
foreach ( $lines as $line ) { foreach ( $lines as $line ) {
@ -94,7 +94,7 @@ function probeProfiles( $device_ep, $soapversion, $username, $password ) {
// add user@pass to URI // add user@pass to URI
if ( preg_match('|^(\S+://)(.+)$|', $stream_uri, $tokens) ) { if ( preg_match('|^(\S+://)(.+)$|', $stream_uri, $tokens) ) {
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2]; $stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
} }
$profile = array( # 'monitor' part of camera $profile = array( # 'monitor' part of camera
'Type' => 'Ffmpeg', 'Type' => 'Ffmpeg',
@ -125,8 +125,8 @@ xhtmlHeaders(__FILE__, translate('MonitorProbe') );
if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) { if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
$monitors = array(); $monitors = array();
foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type = 'Remote' ORDER BY Host") as $monitor ) { foreach ( dbFetchAll("SELECT Id, Name, Host FROM Monitors WHERE Type='Remote' ORDER BY Host") as $monitor ) {
if ( preg_match( '/^(.+)@(.+)$/', $monitor['Host'], $matches ) ) { if ( preg_match('/^(.+)@(.+)$/', $monitor['Host'], $matches) ) {
//echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."<br/>"; //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."<br/>";
$monitors[gethostbyname($matches[2])] = $monitor; $monitors[gethostbyname($matches[2])] = $monitor;
} else { } else {
@ -137,26 +137,12 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
$detcameras = probeCameras(''); $detcameras = probeCameras('');
foreach ( $detcameras as $camera ) { foreach ( $detcameras as $camera ) {
if ( preg_match( '|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches ) ) { if ( preg_match('|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches) ) {
$ip = $matches[1]; $ip = $matches[1];
} }
$host = $ip; $host = $ip;
/*
if ( isset($monitors[$ip]) )
{
$monitor = $monitors[$ip];
$sourceString .= " (".$monitor['Name'].")";
}
else
{
$sourceString .= " - ".translate('Available');
}
$cameras[$sourceDesc] = $sourceString;
}
*/
// $sourceDesc = htmlspecialchars(serialize($camera['monitor']));
$sourceDesc = base64_encode(json_encode($camera['monitor'])); $sourceDesc = base64_encode(json_encode($camera['monitor']));
$sourceString = $camera['model'].' @ '.$host . ' using version ' . $camera['monitor']['SOAP'] ; $sourceString = $camera['model'].' @ '.$host.' using version '.$camera['monitor']['SOAP'];
$cameras[$sourceDesc] = $sourceString; $cameras[$sourceDesc] = $sourceString;
} }
@ -179,39 +165,38 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
</p> </p>
<p> <p>
<label for="probe"><?php echo translate('DetectedCameras') ?></label> <label for="probe"><?php echo translate('DetectedCameras') ?></label>
<?php echo htmlSelect('probe', $cameras, null, array('onchange'=>'configureButtons(this)')); ?> <?php echo htmlSelect('probe', $cameras, null, array('data-on-change-this'=>'configureButtons')); ?>
</p> </p>
<p> <p>
<?php echo translate('OnvifCredentialsIntro') ?> <?php echo translate('OnvifCredentialsIntro') ?>
</p> </p>
<p> <p>
<label for="username"><?php echo translate('Username') ?></label> <label for="Username"><?php echo translate('Username') ?></label>
<input type="text" name="username" value="" onChange="configureButtons(this)"/> <input type="text" name="Username" data-on-change-this="configureButtons"/>
</p> </p>
<p> <p>
<label for="password"><?php echo translate('Password') ?></label> <label for="Password"><?php echo translate('Password') ?></label>
<input type="password" name="password" value="" onChange="configureButtons(this)"/> <input type="password" name="Password" data-on-change-this="configureButtons"/>
</p> </p>
<div id="contentButtons"> <div id="contentButtons">
<input type="button" value="<?php echo translate('Cancel') ?>" data-on-click="closeWindow"/> <button type="button" data-on-click="closeWindow"><?php echo translate('Cancel') ?></button>
<input type="submit" name="nextBtn" value="<?php echo translate('Next') ?>" data-on-click-this="gotoStep2" disabled="disabled"/> <button type="button" name="nextBtn" data-on-click-this="gotoStep2" disabled="disabled"><?php echo translate('Next') ?></button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</body> </body>
</html>
<?php <?php
//==== STEP 2 ============================================================ //==== STEP 2 ============================================================
} else if($_REQUEST['step'] == '2') { } else if ( $_REQUEST['step'] == '2' ) {
if ( empty($_REQUEST['probe']) ) if ( empty($_REQUEST['probe']) )
ZM\Fatal('No probe passed in request. Please go back and try again.'); ZM\Fatal('No probe passed in request. Please go back and try again.');
#|| empty($_REQUEST['username']) || #|| empty($_REQUEST['username']) ||
#empty($_REQUEST['password']) ) #empty($_REQUEST['password']) )
$probe = json_decode(base64_decode($_REQUEST['probe'])); $probe = json_decode(base64_decode($_REQUEST['probe']));
ZM\Logger::Debug(print_r($probe,true)); ZM\Logger::Debug(print_r($probe, true));
foreach ( $probe as $name=>$value ) { foreach ( $probe as $name=>$value ) {
if ( isset($value) ) { if ( isset($value) ) {
$monitor[$name] = $value; $monitor[$name] = $value;
@ -221,7 +206,7 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
//print $monitor['Host'].", ".$_REQUEST['username'].", ".$_REQUEST['password']."<br/>"; //print $monitor['Host'].", ".$_REQUEST['username'].", ".$_REQUEST['password']."<br/>";
$detprofiles = probeProfiles($monitor['Host'], $monitor['SOAP'], $_REQUEST['username'], $_REQUEST['password']); $detprofiles = probeProfiles($monitor['Host'], $monitor['SOAP'], $_REQUEST['Username'], $_REQUEST['Password']);
foreach ( $detprofiles as $profile ) { foreach ( $detprofiles as $profile ) {
$monitor = $camera['monitor']; $monitor = $camera['monitor'];
@ -258,18 +243,18 @@ if ( !isset($_REQUEST['step']) || ($_REQUEST['step'] == '1') ) {
</p> </p>
<p> <p>
<label for="probe"><?php echo translate('DetectedProfiles') ?></label> <label for="probe"><?php echo translate('DetectedProfiles') ?></label>
<?php echo htmlSelect('probe', $profiles, null, array('onchange'=>'configureButtons(this)')); ?> <?php echo htmlSelect('probe', $profiles, null, array('data-on-change-this'=>'configureButtons')); ?>
</p> </p>
<div id="contentButtons"> <div id="contentButtons">
<input type="button" name="prevBtn" value="<?php echo translate('Prev') ?>" data-on-click-this="gotoStep1"/> <button type="button" name="prevBtn" data-on-click-this="gotoStep1"><?php echo translate('Prev') ?></button>
<input type="button" value="<?php echo translate('Cancel') ?>" data-on-click="closeWindow"/> <button type="button" data-on-click="closeWindow"><?php echo translate('Cancel') ?></button>
<input type="submit" name="saveBtn" value="<?php echo translate('Save') ?>" data-on-click-this="submitCamera" disabled="disabled"/> <button type="button" name="saveBtn" data-on-click-this="submitCamera" disabled="disabled"><?php echo translate('Save') ?></button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</body> </body>
</html>
<?php <?php
} // end if step 1 or 2 } // end if step 1 or 2
?> ?>
</html>