move the input packet into a member of the camera. Fix packet copying in packetqueue. Implement separate start pts and dts for audio and video
This commit is contained in:
parent
3dcc1c3697
commit
a5b7b6e74f
|
@ -146,8 +146,6 @@ int FfmpegCamera::Capture( Image &image )
|
||||||
mReopenThread = 0;
|
mReopenThread = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVPacket packet;
|
|
||||||
|
|
||||||
int frameComplete = false;
|
int frameComplete = false;
|
||||||
while ( !frameComplete ) {
|
while ( !frameComplete ) {
|
||||||
int avResult = av_read_frame( mFormatContext, &packet );
|
int avResult = av_read_frame( mFormatContext, &packet );
|
||||||
|
@ -386,9 +384,6 @@ int FfmpegCamera::OpenFfmpeg() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
Debug ( 1, "Opened codec" );
|
Debug ( 1, "Opened codec" );
|
||||||
|
|
||||||
// Allocate space for the native video frame
|
// Allocate space for the native video frame
|
||||||
|
@ -563,13 +558,12 @@ int FfmpegCamera::CaptureAndRecord( Image &image, bool recording, char* event_fi
|
||||||
|
|
||||||
int frameComplete = false;
|
int frameComplete = false;
|
||||||
while ( !frameComplete ) {
|
while ( !frameComplete ) {
|
||||||
// We are now allocating dynamically because we need to queue these and may go out of scope.
|
Debug(2, "Before av_init_packe");
|
||||||
AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
|
av_init_packet( &packet );
|
||||||
av_init_packet( packet );
|
|
||||||
|
|
||||||
Debug(5, "Before av_read_frame");
|
Debug(2, "Before av_read_frame");
|
||||||
ret = av_read_frame( mFormatContext, packet );
|
ret = av_read_frame( mFormatContext, &packet );
|
||||||
Debug(5, "After av_read_frame (%d)", ret );
|
Debug(2, "After av_read_frame (%d)", ret );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
if (
|
if (
|
||||||
|
@ -582,21 +576,33 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
ReopenFfmpeg();
|
ReopenFfmpeg();
|
||||||
}
|
}
|
||||||
|
|
||||||
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet->stream_index, ret, errbuf );
|
Error( "Unable to read packet from stream %d: error %d \"%s\".", packet.stream_index, ret, errbuf );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
Debug( 4, "Got packet from stream %d dts (%d) pts(%d)", packet->stream_index, packet->dts, packet->pts );
|
Debug( 3, "Got packet from stream %d dts (%d) pts(%d) key?(%d)", packet.stream_index, packet.dts, packet.pts, packet.flags & AV_PKT_FLAG_KEY );
|
||||||
|
//av_packet_ref( &packet, &packet );
|
||||||
|
|
||||||
//Video recording
|
//Video recording
|
||||||
if ( recording ) {
|
if ( recording ) {
|
||||||
|
Debug(3, "recording:");
|
||||||
// The directory we are recording to is no longer tied to the current event.
|
// The directory we are recording to is no longer tied to the current event.
|
||||||
// Need to re-init the videostore with the correct directory and start recording again
|
// Need to re-init the videostore with the correct directory and start recording again
|
||||||
// for efficiency's sake, we should test for keyframe before we test for directory change...
|
// for efficiency's sake, we should test for keyframe before we test for directory change...
|
||||||
if ( videoStore && (packet->flags & AV_PKT_FLAG_KEY) && (strcmp(oldDirectory, event_file) != 0 ) ) {
|
if ( videoStore && (packet.flags & AV_PKT_FLAG_KEY) && (strcmp(oldDirectory, event_file) != 0 ) ) {
|
||||||
// don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?...
|
// don't open new videostore until we're on a key frame..would this require an offset adjustment for the event as a result?...
|
||||||
// if we store our key frame location with the event will that be enough?
|
// if we store our key frame location with the event will that be enough?
|
||||||
Info("Re-starting video storage module");
|
Info("Re-starting video storage module");
|
||||||
|
|
||||||
|
// I don't know if this is important or not... but I figure we might as well write this last packet out to the store before closing it.
|
||||||
|
// Also don't know how much it matters for audio.
|
||||||
|
if ( packet.stream_index == mVideoStreamId ) {
|
||||||
|
//Write the packet to our video store
|
||||||
|
int ret = videoStore->writeVideoFramePacket( &packet );
|
||||||
|
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||||
|
Warning("Error writing last packet to videostore.");
|
||||||
|
}
|
||||||
|
} // end if video
|
||||||
|
|
||||||
delete videoStore;
|
delete videoStore;
|
||||||
videoStore = NULL;
|
videoStore = NULL;
|
||||||
}
|
}
|
||||||
|
@ -637,11 +643,11 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
while ( ( queued_packet = packetqueue.popPacket() ) ) {
|
||||||
packet_count += 1;
|
packet_count += 1;
|
||||||
//Write the packet to our video store
|
//Write the packet to our video store
|
||||||
Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
|
Debug(2, "Writing queued packet stream: %d KEY %d, remaining (%d)", queued_packet->stream_index, queued_packet->flags & AV_PKT_FLAG_KEY, packetqueue.size() );
|
||||||
if ( queued_packet->stream_index == mVideoStreamId ) {
|
if ( queued_packet->stream_index == mVideoStreamId ) {
|
||||||
ret = videoStore->writeVideoFramePacket( queued_packet, mFormatContext->streams[mVideoStreamId]);
|
ret = videoStore->writeVideoFramePacket( queued_packet );
|
||||||
} else if ( queued_packet->stream_index == mAudioStreamId ) {
|
} else if ( queued_packet->stream_index == mAudioStreamId ) {
|
||||||
ret = videoStore->writeAudioFramePacket( queued_packet, mFormatContext->streams[mAudioStreamId]);
|
ret = videoStore->writeAudioFramePacket( queued_packet );
|
||||||
} else {
|
} else {
|
||||||
Warning("Unknown stream id in queued packet (%d)", queued_packet->stream_index );
|
Warning("Unknown stream id in queued packet (%d)", queued_packet->stream_index );
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
@ -663,27 +669,32 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
videoStore = NULL;
|
videoStore = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Buffer video packets, since we are not recording
|
//Buffer video packets, since we are not recording. All audio packets are keyframes, so only if it's a video keyframe
|
||||||
if ( (packet->stream_index == mVideoStreamId) && ( packet->flags & AV_PKT_FLAG_KEY ) ) {
|
if ( (packet.stream_index == mVideoStreamId) && ( packet.flags & AV_PKT_FLAG_KEY ) ) {
|
||||||
|
Debug(3, "Clearing queue");
|
||||||
packetqueue.clearQueue();
|
packetqueue.clearQueue();
|
||||||
}
|
}
|
||||||
packetqueue.queuePacket(packet);
|
if ( packet.stream_index != mAudioStreamId || record_audio ) {
|
||||||
} // end if
|
Debug(3, "Queuing");
|
||||||
|
packetqueue.queuePacket( &packet );
|
||||||
|
}
|
||||||
|
} // end if recording or not
|
||||||
|
|
||||||
if ( packet->stream_index == mVideoStreamId ) {
|
if ( packet.stream_index == mVideoStreamId ) {
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
//Write the packet to our video store
|
//Write the packet to our video store
|
||||||
int ret = videoStore->writeVideoFramePacket( packet, mFormatContext->streams[mVideoStreamId] );
|
int ret = videoStore->writeVideoFramePacket( &packet );
|
||||||
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||||
zm_av_unref_packet( packet );
|
zm_av_unref_packet( &packet );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, packet );
|
Debug(3, "about to decode video" );
|
||||||
|
ret = zm_avcodec_decode_video( mVideoCodecContext, mRawFrame, &frameComplete, &packet );
|
||||||
if ( ret < 0 ) {
|
if ( ret < 0 ) {
|
||||||
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
av_strerror( ret, errbuf, AV_ERROR_MAX_STRING_SIZE );
|
||||||
Error( "Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf );
|
Error( "Unable to decode frame at frame %d: %s, continuing", frameCount, errbuf );
|
||||||
zm_av_unref_packet( packet );
|
zm_av_unref_packet( &packet );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,7 +709,7 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
|
||||||
if ( directbuffer == NULL ) {
|
if ( directbuffer == NULL ) {
|
||||||
Error("Failed requesting writeable buffer for the captured image.");
|
Error("Failed requesting writeable buffer for the captured image.");
|
||||||
zm_av_unref_packet( packet );
|
zm_av_unref_packet( &packet );
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height);
|
||||||
|
@ -727,16 +738,16 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
} else {
|
} else {
|
||||||
Debug( 3, "Not framecomplete after av_read_frame" );
|
Debug( 3, "Not framecomplete after av_read_frame" );
|
||||||
} // end if frameComplete
|
} // end if frameComplete
|
||||||
} else if ( packet->stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
} else if ( packet.stream_index == mAudioStreamId ) { //FIXME best way to copy all other streams
|
||||||
Debug( 4, "Audio stream index %d", packet->stream_index );
|
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
if ( record_audio ) {
|
if ( record_audio ) {
|
||||||
Debug(3, "Recording audio packet streamindex(%d) packetstreamindex(%d)", mAudioStreamId, packet->stream_index );
|
Debug(3, "Recording audio packet streamindex(%d) packetstreamindex(%d)", mAudioStreamId, packet.stream_index );
|
||||||
//Write the packet to our video store
|
//Write the packet to our video store
|
||||||
//FIXME no relevance of last key frame
|
//FIXME no relevance of last key frame
|
||||||
int ret = videoStore->writeAudioFramePacket( packet, mFormatContext->streams[packet->stream_index] );
|
int ret = videoStore->writeAudioFramePacket( &packet );
|
||||||
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
||||||
zm_av_unref_packet( packet );
|
Warning("Failure to write audio packet.");
|
||||||
|
zm_av_unref_packet( &packet );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -745,15 +756,16 @@ Debug(5, "After av_read_frame (%d)", ret );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if LIBAVUTIL_VERSION_CHECK(54, 23, 0, 23, 0)
|
#if LIBAVUTIL_VERSION_CHECK(54, 23, 0, 23, 0)
|
||||||
Debug( 3, "Some other stream index %d, %s", packet->stream_index, av_get_media_type_string( mFormatContext->streams[packet->stream_index]->codec->codec_type) );
|
Debug( 3, "Some other stream index %d, %s", packet.stream_index, av_get_media_type_string( mFormatContext->streams[packet.stream_index]->codec->codec_type) );
|
||||||
#else
|
#else
|
||||||
Debug( 3, "Some other stream index %d", packet->stream_index );
|
Debug( 3, "Some other stream index %d", packet.stream_index );
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if ( videoStore ) {
|
//if ( videoStore ) {
|
||||||
zm_av_unref_packet( packet );
|
|
||||||
av_free( packet );
|
// the packet contents are ref counted... when queuing, we allocate another packet and reference it with that one, so we should always need to unref here, which should not affect the queued version.
|
||||||
}
|
zm_av_unref_packet( &packet );
|
||||||
|
//}
|
||||||
} // end while ! frameComplete
|
} // end while ! frameComplete
|
||||||
return (frameCount);
|
return (frameCount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,11 @@ class FfmpegCamera : public Camera
|
||||||
AVFrame *mFrame;
|
AVFrame *mFrame;
|
||||||
_AVPIXELFORMAT imagePixFormat;
|
_AVPIXELFORMAT imagePixFormat;
|
||||||
|
|
||||||
|
// Used to store the incoming packet, it will get copied when queued.
|
||||||
|
// We only ever need one at a time, so instead of constantly allocating
|
||||||
|
// and freeing this structure, we will just make it a member of the object.
|
||||||
|
AVPacket packet;
|
||||||
|
|
||||||
int OpenFfmpeg();
|
int OpenFfmpeg();
|
||||||
int ReopenFfmpeg();
|
int ReopenFfmpeg();
|
||||||
int CloseFfmpeg();
|
int CloseFfmpeg();
|
||||||
|
@ -67,11 +72,9 @@ class FfmpegCamera : public Camera
|
||||||
bool wasRecording;
|
bool wasRecording;
|
||||||
VideoStore *videoStore;
|
VideoStore *videoStore;
|
||||||
char oldDirectory[4096];
|
char oldDirectory[4096];
|
||||||
|
unsigned int old_event_id;
|
||||||
zm_packetqueue packetqueue;
|
zm_packetqueue packetqueue;
|
||||||
|
|
||||||
// Last Key frame
|
|
||||||
//AVPacket lastKeyframePkt;
|
|
||||||
|
|
||||||
#if HAVE_LIBSWSCALE
|
#if HAVE_LIBSWSCALE
|
||||||
struct SwsContext *mConvertContext;
|
struct SwsContext *mConvertContext;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -35,17 +35,18 @@ zm_packetqueue::~zm_packetqueue() {
|
||||||
|
|
||||||
bool zm_packetqueue::queuePacket( AVPacket* packet ) {
|
bool zm_packetqueue::queuePacket( AVPacket* packet ) {
|
||||||
|
|
||||||
//AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket));
|
AVPacket *input_ref = (AVPacket *)av_malloc(sizeof(AVPacket));
|
||||||
//if ( av_packet_ref( input_ref, packet ) < 0 ) {
|
av_init_packet( input_ref );
|
||||||
if ( 0 ) {
|
if ( av_packet_ref( input_ref, packet ) < 0 ) {
|
||||||
if ( av_packet_ref( packet, packet ) < 0 ) {
|
|
||||||
Error("error refing packet");
|
Error("error refing packet");
|
||||||
//av_free_packet(input_ref);
|
av_free(input_ref);
|
||||||
return false;
|
return false;
|
||||||
}
|
} else {
|
||||||
|
Debug(3, "made a ref");
|
||||||
}
|
}
|
||||||
|
|
||||||
pktQueue.push( packet );
|
pktQueue.push( input_ref );
|
||||||
|
Debug(3, "queued");
|
||||||
//pktQueue.push( input_ref );
|
//pktQueue.push( input_ref );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -523,7 +523,7 @@ int RemoteCameraRtsp::CaptureAndRecord(Image &image, bool recording, char* event
|
||||||
|
|
||||||
if ( videoStore ) {
|
if ( videoStore ) {
|
||||||
//Write the packet to our video store
|
//Write the packet to our video store
|
||||||
int ret = videoStore->writeVideoFramePacket(&packet, mFormatContext->streams[mVideoStreamId]);//, &lastKeyframePkt);
|
int ret = videoStore->writeVideoFramePacket(&packet);//, &lastKeyframePkt);
|
||||||
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
if ( ret < 0 ) {//Less than zero and we skipped a frame
|
||||||
// Should not
|
// Should not
|
||||||
av_free_packet( &packet );
|
av_free_packet( &packet );
|
||||||
|
@ -553,7 +553,7 @@ int RemoteCameraRtsp::CaptureAndRecord(Image &image, bool recording, char* event
|
||||||
if ( videoStore && record_audio ) {
|
if ( videoStore && record_audio ) {
|
||||||
Debug( 4, "Storing Audio packet" );
|
Debug( 4, "Storing Audio packet" );
|
||||||
//Write the packet to our video store
|
//Write the packet to our video store
|
||||||
int ret = videoStore->writeAudioFramePacket(&packet, mFormatContext->streams[packet.stream_index]); //FIXME no relevance of last key frame
|
int ret = videoStore->writeAudioFramePacket( &packet ); //FIXME no relevance of last key frame
|
||||||
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
if ( ret < 0 ) { //Less than zero and we skipped a frame
|
||||||
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
#if LIBAVCODEC_VERSION_CHECK(57, 8, 0, 12, 100)
|
||||||
av_packet_unref( &packet );
|
av_packet_unref( &packet );
|
||||||
|
|
|
@ -33,11 +33,13 @@ extern "C"{
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
VideoStore::VideoStore(const char *filename_in, const char *format_in,
|
||||||
AVStream *input_video_stream,
|
AVStream *p_input_video_stream,
|
||||||
AVStream *input_audio_stream,
|
AVStream *p_input_audio_stream,
|
||||||
int64_t nStartTime,
|
int64_t nStartTime,
|
||||||
Monitor::Orientation orientation
|
Monitor::Orientation orientation
|
||||||
) {
|
) {
|
||||||
|
input_video_stream = p_input_video_stream;
|
||||||
|
input_audio_stream = p_input_audio_stream;
|
||||||
|
|
||||||
//store inputs in variables local to class
|
//store inputs in variables local to class
|
||||||
filename = filename_in;
|
filename = filename_in;
|
||||||
|
@ -296,13 +298,16 @@ Debug(2, "Have audio_output_context");
|
||||||
}
|
}
|
||||||
|
|
||||||
prevDts = 0;
|
prevDts = 0;
|
||||||
startPts = 0;
|
video_start_pts = 0;
|
||||||
startDts = 0;
|
video_start_dts = 0;
|
||||||
|
audio_start_pts = 0;
|
||||||
|
audio_start_dts = 0;
|
||||||
|
|
||||||
filter_in_rescale_delta_last = AV_NOPTS_VALUE;
|
filter_in_rescale_delta_last = AV_NOPTS_VALUE;
|
||||||
|
|
||||||
// now - when streaming started
|
// now - when streaming started
|
||||||
startTime=av_gettime()-nStartTime;//oc->start_time;
|
//startTime=av_gettime()-nStartTime;//oc->start_time;
|
||||||
Info("VideoStore startTime=%d\n",startTime);
|
//Info("VideoStore startTime=%d\n",startTime);
|
||||||
} // VideoStore::VideoStore
|
} // VideoStore::VideoStore
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,7 +360,7 @@ void VideoStore::dumpPacket( AVPacket *pkt ){
|
||||||
Debug(1, "%s:%d:DEBUG: %s", __FILE__, __LINE__, b);
|
Debug(1, "%s:%d:DEBUG: %s", __FILE__, __LINE__, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stream){
|
int VideoStore::writeVideoFramePacket( AVPacket *ipkt ) {
|
||||||
|
|
||||||
AVPacket opkt;
|
AVPacket opkt;
|
||||||
AVPicture pict;
|
AVPicture pict;
|
||||||
|
@ -366,13 +371,13 @@ int VideoStore::writeVideoFramePacket(AVPacket *ipkt, AVStream *input_video_stre
|
||||||
if ( 1 ) {
|
if ( 1 ) {
|
||||||
//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 (ipkt->pts != AV_NOPTS_VALUE) {
|
if (ipkt->pts != AV_NOPTS_VALUE) {
|
||||||
if ( ! startPts ) {
|
if ( ! video_start_pts ) {
|
||||||
//never gets set, so the first packet can set it.
|
//never gets set, so the first packet can set it.
|
||||||
startPts = ipkt->pts;
|
video_start_pts = ipkt->pts;
|
||||||
}
|
}
|
||||||
opkt.pts = av_rescale_q(ipkt->pts-startPts, input_video_stream->time_base, video_stream->time_base);
|
opkt.pts = av_rescale_q(ipkt->pts - video_start_pts, input_video_stream->time_base, video_stream->time_base);
|
||||||
//- ost_tb_start_time;
|
//- ost_tb_start_time;
|
||||||
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, startPts );
|
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, video_start_pts );
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "opkt.pts = undef");
|
Debug(3, "opkt.pts = undef");
|
||||||
opkt.pts = AV_NOPTS_VALUE;
|
opkt.pts = AV_NOPTS_VALUE;
|
||||||
|
@ -380,23 +385,22 @@ if ( 1 ) {
|
||||||
|
|
||||||
//Scale the DTS of the outgoing packet to be the correct time base
|
//Scale the DTS of the outgoing packet to be the correct time base
|
||||||
if(ipkt->dts == AV_NOPTS_VALUE) {
|
if(ipkt->dts == AV_NOPTS_VALUE) {
|
||||||
if ( ! startDts ) startDts = input_video_stream->cur_dts;
|
// why are we using cur_dts instead of packet.dts?
|
||||||
opkt.dts = av_rescale_q(input_video_stream->cur_dts-startDts, AV_TIME_BASE_Q, video_stream->time_base);
|
if ( ! video_start_dts ) video_start_dts = input_video_stream->cur_dts;
|
||||||
|
opkt.dts = av_rescale_q(input_video_stream->cur_dts - video_start_dts, AV_TIME_BASE_Q, video_stream->time_base);
|
||||||
Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d)",
|
Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d)",
|
||||||
opkt.dts, input_video_stream->cur_dts, startDts
|
opkt.dts, input_video_stream->cur_dts, video_start_dts
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if ( ! startDts ) startDts = ipkt->dts;
|
if ( ! video_start_dts ) video_start_dts = ipkt->dts;
|
||||||
opkt.dts = av_rescale_q(ipkt->dts - startDts, input_video_stream->time_base, video_stream->time_base);
|
opkt.dts = av_rescale_q(ipkt->dts - video_start_dts, input_video_stream->time_base, video_stream->time_base);
|
||||||
Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, startDts );
|
Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, video_start_dts );
|
||||||
}
|
}
|
||||||
if ( opkt.dts > opkt.pts ) {
|
if ( opkt.dts > opkt.pts ) {
|
||||||
Warning("opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
|
Debug( 1, "opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
|
||||||
opkt.dts = opkt.pts;
|
opkt.dts = opkt.pts;
|
||||||
}
|
}
|
||||||
|
|
||||||
//opkt.dts -= ost_tb_start_time;
|
|
||||||
|
|
||||||
opkt.duration = av_rescale_q(ipkt->duration, input_video_stream->time_base, video_stream->time_base);
|
opkt.duration = av_rescale_q(ipkt->duration, input_video_stream->time_base, video_stream->time_base);
|
||||||
} else {
|
} else {
|
||||||
av_packet_rescale_ts( &opkt, input_video_stream->time_base, video_stream->time_base );
|
av_packet_rescale_ts( &opkt, input_video_stream->time_base, video_stream->time_base );
|
||||||
|
@ -459,8 +463,8 @@ Debug(4, "Not video and RAWPICTURE");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stream){
|
int VideoStore::writeAudioFramePacket( AVPacket *ipkt ) {
|
||||||
Debug(2, "writeAudioFrame");
|
Debug(4, "writeAudioFrame");
|
||||||
|
|
||||||
if(!audio_stream) {
|
if(!audio_stream) {
|
||||||
Error("Called writeAudioFramePacket when no audio_stream");
|
Error("Called writeAudioFramePacket when no audio_stream");
|
||||||
|
@ -471,8 +475,6 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stre
|
||||||
//zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
|
//zm_dump_stream_format( oc, ipkt->stream_index, 0, 1 );
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
// What is this doing? Getting the time of the start of this video chunk? Does that actually make sense?
|
|
||||||
int64_t ost_tb_start_time = av_rescale_q(startTime, AV_TIME_BASE_Q, audio_stream->time_base);
|
|
||||||
|
|
||||||
AVPacket opkt;
|
AVPacket opkt;
|
||||||
|
|
||||||
|
@ -481,51 +483,42 @@ int VideoStore::writeAudioFramePacket(AVPacket *ipkt, AVStream *input_audio_stre
|
||||||
|
|
||||||
//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 (ipkt->pts != AV_NOPTS_VALUE) {
|
if (ipkt->pts != AV_NOPTS_VALUE) {
|
||||||
Debug(2, "Rescaling output pts");
|
if ( ! audio_start_pts ) {
|
||||||
opkt.pts = av_rescale_q(ipkt->pts-startPts, input_audio_stream->time_base, audio_stream->time_base) - ost_tb_start_time;
|
//never gets set, so the first packet can set it.
|
||||||
|
audio_start_pts = ipkt->pts;
|
||||||
|
}
|
||||||
|
opkt.pts = av_rescale_q(ipkt->pts-audio_start_pts, input_audio_stream->time_base, audio_stream->time_base);
|
||||||
|
Debug(3, "opkt.pts = %d from ipkt->pts(%d) - startPts(%d)", opkt.pts, ipkt->pts, audio_start_pts );
|
||||||
} else {
|
} else {
|
||||||
Debug(2, "Setting output pts to AV_NOPTS_VALUE");
|
Debug(3, "opkt.pts = undef");
|
||||||
opkt.pts = AV_NOPTS_VALUE;
|
opkt.pts = AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Scale the DTS of the outgoing packet to be the correct time base
|
//Scale the DTS of the outgoing packet to be the correct time base
|
||||||
if(ipkt->dts == AV_NOPTS_VALUE) {
|
if(ipkt->dts == AV_NOPTS_VALUE) {
|
||||||
Debug(2, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
if ( ! audio_start_dts ) audio_start_dts = input_video_stream->cur_dts;
|
||||||
opkt.dts = av_rescale_q(input_audio_stream->cur_dts-startDts, AV_TIME_BASE_Q, audio_stream->time_base);
|
opkt.dts = av_rescale_q(input_video_stream->cur_dts - audio_start_dts, AV_TIME_BASE_Q, audio_stream->time_base);
|
||||||
Debug(2, "ipkt->dts == AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
Debug(3, "opkt.dts = %d from input_video_stream->cur_dts(%d) - startDts(%d)",
|
||||||
|
opkt.dts, input_audio_stream->cur_dts, audio_start_dts
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
Debug(2, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
if ( ! audio_start_dts ) audio_start_dts = ipkt->dts;
|
||||||
opkt.dts = av_rescale_q(ipkt->dts-startDts, input_audio_stream->time_base, audio_stream->time_base);
|
opkt.dts = av_rescale_q(ipkt->dts - audio_start_dts, input_audio_stream->time_base, audio_stream->time_base);
|
||||||
Debug(2, "ipkt->dts != AV_NOPTS_VALUE %d to %d", AV_NOPTS_VALUE, opkt.dts );
|
Debug(3, "opkt.dts = %d from ipkt->dts(%d) - startDts(%d)", opkt.dts, ipkt->dts, audio_start_dts );
|
||||||
}
|
}
|
||||||
Debug(2, "Not sure what ost_tb_start_time is (%d) - (%d)", opkt.dts, ost_tb_start_time );
|
if ( opkt.dts > opkt.pts ) {
|
||||||
opkt.dts -= ost_tb_start_time;
|
Debug(1,"opkt.dts(%d) must be <= opkt.pts(%d). Decompression must happen before presentation.", opkt.dts, opkt.pts );
|
||||||
|
opkt.dts = opkt.pts;
|
||||||
// Seems like it would be really weird for the codec type to NOT be audiu
|
|
||||||
if (audio_stream->codec->codec_type == AVMEDIA_TYPE_AUDIO && ipkt->dts != AV_NOPTS_VALUE) {
|
|
||||||
int duration = av_get_audio_frame_duration(input_audio_stream->codec, ipkt->size);
|
|
||||||
Debug( 1, "code is audio, dts != AV_NOPTS_VALUE got duration(%d)", duration );
|
|
||||||
if ( ! duration ) {
|
|
||||||
duration = input_audio_stream->codec->frame_size;
|
|
||||||
Warning( "got no duration from av_get_audio_frame_duration. Using frame size(%d)", duration );
|
|
||||||
}
|
|
||||||
|
|
||||||
//FIXME where to get filter_in_rescale_delta_last
|
|
||||||
//FIXME av_rescale_delta doesn't exist in ubuntu vivid libavtools
|
|
||||||
opkt.dts = opkt.pts = av_rescale_delta(input_audio_stream->time_base, ipkt->dts,
|
|
||||||
(AVRational){1, input_audio_stream->codec->sample_rate}, duration, &filter_in_rescale_delta_last,
|
|
||||||
audio_stream->time_base) - ost_tb_start_time;
|
|
||||||
Debug(2, "rescaled dts is: (%d)", opkt.dts );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opkt.duration = av_rescale_q(ipkt->duration, input_audio_stream->time_base, audio_stream->time_base);
|
opkt.duration = av_rescale_q(ipkt->duration, input_audio_stream->time_base, audio_stream->time_base);
|
||||||
|
// pkt.pos: byte position in stream, -1 if unknown
|
||||||
opkt.pos = -1;
|
opkt.pos = -1;
|
||||||
opkt.flags = ipkt->flags;
|
opkt.flags = ipkt->flags;
|
||||||
opkt.stream_index = ipkt->stream_index;
|
opkt.stream_index = ipkt->stream_index;
|
||||||
|
|
||||||
if ( audio_output_codec ) {
|
if ( audio_output_codec ) {
|
||||||
|
// we are transcoding
|
||||||
|
|
||||||
|
|
||||||
AVFrame *input_frame;
|
AVFrame *input_frame;
|
||||||
AVFrame *output_frame;
|
AVFrame *output_frame;
|
||||||
|
|
|
@ -15,6 +15,9 @@ private:
|
||||||
AVStream *video_stream;
|
AVStream *video_stream;
|
||||||
AVStream *audio_stream;
|
AVStream *audio_stream;
|
||||||
|
|
||||||
|
AVStream *input_video_stream;
|
||||||
|
AVStream *input_audio_stream;
|
||||||
|
|
||||||
// The following are used when encoding the audio stream to AAC
|
// The following are used when encoding the audio stream to AAC
|
||||||
AVCodec *audio_output_codec;
|
AVCodec *audio_output_codec;
|
||||||
AVCodecContext *audio_output_context;
|
AVCodecContext *audio_output_context;
|
||||||
|
@ -26,9 +29,11 @@ private:
|
||||||
bool keyframeMessage;
|
bool keyframeMessage;
|
||||||
int keyframeSkipNumber;
|
int keyframeSkipNumber;
|
||||||
|
|
||||||
int64_t startTime;
|
int64_t video_start_pts;
|
||||||
int64_t startPts;
|
int64_t video_start_dts;
|
||||||
int64_t startDts;
|
int64_t audio_start_pts;
|
||||||
|
int64_t audio_start_dts;
|
||||||
|
|
||||||
int64_t prevDts;
|
int64_t prevDts;
|
||||||
int64_t filter_in_rescale_delta_last;
|
int64_t filter_in_rescale_delta_last;
|
||||||
|
|
||||||
|
@ -36,23 +41,11 @@ public:
|
||||||
VideoStore(const char *filename_in, const char *format_in, AVStream *input_video_stream, AVStream *input_audio_stream, int64_t nStartTime, Monitor::Orientation p_orientation );
|
VideoStore(const char *filename_in, const char *format_in, AVStream *input_video_stream, AVStream *input_audio_stream, int64_t nStartTime, Monitor::Orientation p_orientation );
|
||||||
~VideoStore();
|
~VideoStore();
|
||||||
|
|
||||||
int writeVideoFramePacket(AVPacket *pkt, AVStream *input_st);//, AVPacket *lastKeyframePkt);
|
int writeVideoFramePacket( AVPacket *pkt );
|
||||||
int writeAudioFramePacket(AVPacket *pkt, AVStream *input_st);
|
int writeAudioFramePacket( AVPacket *pkt );
|
||||||
void dumpPacket( AVPacket *pkt );
|
void dumpPacket( AVPacket *pkt );
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
class VideoEvent {
|
|
||||||
public:
|
|
||||||
VideoEvent(unsigned int eid);
|
|
||||||
~VideoEvent();
|
|
||||||
|
|
||||||
int createEventImage(unsigned int fid, char *&pBuff);
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned int m_eid;
|
|
||||||
};*/
|
|
||||||
|
|
||||||
#endif //havelibav
|
#endif //havelibav
|
||||||
#endif //zm_videostore_h
|
#endif //zm_videostore_h
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,10 @@ void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_
|
||||||
overload_frames = p_overload_frames;
|
overload_frames = p_overload_frames;
|
||||||
extend_alarm_frames = p_extend_alarm_frames;
|
extend_alarm_frames = p_extend_alarm_frames;
|
||||||
|
|
||||||
Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames );
|
//Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d, AF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames, extend_alarm_frames );
|
||||||
|
//Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames );
|
||||||
|
//Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method );
|
||||||
|
Debug( 1, "Initialised zone %d/%s - %d - %dx%d", id, label, type, polygon.Width(), polygon.Height() );
|
||||||
|
|
||||||
alarmed = false;
|
alarmed = false;
|
||||||
pixel_diff = 0;
|
pixel_diff = 0;
|
||||||
|
|
Loading…
Reference in New Issue