Skip to content

Commit

Permalink
updates for mast ffmpeg
Browse files Browse the repository at this point in the history
  • Loading branch information
APHW2 MFGENG committed Nov 8, 2017
1 parent 2ffa791 commit e17bcb9
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 247 deletions.
2 changes: 2 additions & 0 deletions src/zm_ffmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ int av_dict_parse_string(AVDictionary **pm, const char *str,
#endif // HAVE_LIBAVCODEC || HAVE_LIBAVUTIL || HAVE_LIBSWSCALE

#if HAVE_LIBAVUTIL
#if LIBAVUTIL_VERSION_CHECK(56, 0, 0, 17, 100)
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb){
int64_t a, b, this_thing;

Expand All @@ -156,6 +157,7 @@ int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int
return av_rescale_q(this_thing, fs_tb, out_tb);
}
#endif
#endif

int hacked_up_context2_for_older_ffmpeg(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename) {
AVFormatContext *s = avformat_alloc_context();
Expand Down
2 changes: 2 additions & 0 deletions src/zm_ffmpeg_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,9 @@ int FfmpegCamera::OpenFfmpeg() {
// STolen from ispy
//this fixes issues with rtsp streams!! woot.
//mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG2_CHUNKS | CODEC_FLAG_LOW_DELAY; // Enable faster H264 decode.
#ifdef CODEC_FLAG2_FAST
mVideoCodecContext->flags2 |= CODEC_FLAG2_FAST | CODEC_FLAG_LOW_DELAY;
#endif

#if HAVE_AVUTIL_HWCONTEXT_H
if ( mVideoCodecContext->codec_id == AV_CODEC_ID_H264 ) {
Expand Down
133 changes: 85 additions & 48 deletions src/zm_mpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,39 +211,52 @@ void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int hei

Debug( 1, "Allocated stream" );

AVCodecContext *c = ost->codec;
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context = avcodec_alloc_context3(NULL);
avcodec_parameters_to_context(codec_context, ost->codecpar);
#else
codec_context = ost->codec;
#endif

c->codec_id = codec->id;
c->codec_type = codec->type;
codec_context->codec_id = codec->id;
codec_context->codec_type = codec->type;

c->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
codec_context->pix_fmt = strcmp( "mjpeg", ofc->oformat->name ) == 0 ? AV_PIX_FMT_YUVJ422P : AV_PIX_FMT_YUV420P;
if ( bitrate <= 100 ) {
// Quality based bitrate control (VBR). Scale is 1..31 where 1 is best.
// This gets rid of artifacts in the beginning of the movie; and well, even quality.
c->flags |= CODEC_FLAG_QSCALE;
c->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
codec_context->flags |= AV_CODEC_FLAG_QSCALE;
#else
codec_context->flags |= CODEC_FLAG_QSCALE;
#endif
codec_context->global_quality = FF_QP2LAMBDA * (31 - (31 * (bitrate / 100.0)));
} else {
c->bit_rate = bitrate;
codec_context->bit_rate = bitrate;
}

/* resolution must be a multiple of two */
c->width = width;
c->height = height;
codec_context->width = width;
codec_context->height = height;
/* time base: this is the fundamental unit of time (in seconds) in terms
of which frame timestamps are represented. for fixed-fps content,
timebase should be 1/framerate and timestamp increments should be
identically 1. */
c->time_base.den = frame_rate;
c->time_base.num = 1;
codec_context->time_base.den = frame_rate;
codec_context->time_base.num = 1;

Debug( 1, "Will encode in %d fps.", c->time_base.den );
Debug( 1, "Will encode in %d fps.", codec_context->time_base.den );

/* emit one intra frame every second */
c->gop_size = frame_rate;
codec_context->gop_size = frame_rate;

// some formats want stream headers to be separate
if ( of->flags & AVFMT_GLOBALHEADER )
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
#if LIBAVCODEC_VERSION_CHECK(56, 35, 0, 64, 0)
codec_context->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
#else
codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif
} else {
Fatal( "of->video_codec == AV_CODEC_ID_NONE" );
}
Expand Down Expand Up @@ -278,13 +291,11 @@ void VideoStream::OpenStream( ) {
/* now that all the parameters are set, we can open the
video codecs and allocate the necessary encode buffers */
if ( ost ) {
AVCodecContext *c = ost->codec;

/* open the codec */
#if !LIBAVFORMAT_VERSION_CHECK(53, 8, 0, 8, 0)
if ( (avRet = avcodec_open( c, codec )) < 0 )
if ( (avRet = avcodec_open( codec_context, codec )) < 0 )
#else
if ( (avRet = avcodec_open2( c, codec, 0 )) < 0 )
if ( (avRet = avcodec_open2( codec_context, codec, 0 )) < 0 )
#endif
{
Fatal( "Could not open codec. Error code %d \"%s\"", avRet, av_err2str( avRet ) );
Expand All @@ -293,19 +304,15 @@ void VideoStream::OpenStream( ) {
Debug( 1, "Opened codec" );

/* allocate the encoded raw picture */
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
opicture = av_frame_alloc( );
#else
opicture = avcodec_alloc_frame( );
#endif
opicture = zm_av_frame_alloc( );
if ( !opicture ) {
Panic( "Could not allocate opicture" );
}

#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( c->pix_fmt, c->width, c->height, 1 );
int size = av_image_get_buffer_size( codec_context->pix_fmt, codec_context->width, codec_context->height, 1 );
#else
int size = avpicture_get_size( c->pix_fmt, c->width, c->height );
int size = avpicture_get_size( codec_context->pix_fmt, codec_context->width, codec_context->height );
#endif

uint8_t *opicture_buf = (uint8_t *)av_malloc( size );
Expand All @@ -315,17 +322,17 @@ void VideoStream::OpenStream( ) {
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(opicture->data, opicture->linesize,
opicture_buf, c->pix_fmt, c->width, c->height, 1);
opicture_buf, codec_context->pix_fmt, codec_context->width, codec_context->height, 1);
#else
avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt,
c->width, c->height );
avpicture_fill( (AVPicture *)opicture, opicture_buf, codec_context->pix_fmt,
codec_context->width, codec_context->height );
#endif

/* if the output format is not identical to the input format, then a temporary
picture is needed too. It is then converted to the required
output format */
tmp_opicture = NULL;
if ( c->pix_fmt != pf ) {
if ( codec_context->pix_fmt != pf ) {
#if LIBAVCODEC_VERSION_CHECK(55, 28, 1, 45, 101)
tmp_opicture = av_frame_alloc( );
#else
Expand All @@ -335,9 +342,9 @@ void VideoStream::OpenStream( ) {
Panic( "Could not allocate tmp_opicture" );
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
int size = av_image_get_buffer_size( pf, c->width, c->height,1 );
int size = av_image_get_buffer_size( pf, codec_context->width, codec_context->height,1 );
#else
int size = avpicture_get_size( pf, c->width, c->height );
int size = avpicture_get_size( pf, codec_context->width, codec_context->height );
#endif
uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc( size );
if ( !tmp_opicture_buf ) {
Expand All @@ -347,10 +354,10 @@ void VideoStream::OpenStream( ) {
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
av_image_fill_arrays(tmp_opicture->data,
tmp_opicture->linesize, tmp_opicture_buf, pf,
c->width, c->height, 1);
codec_context->width, codec_context->height, 1);
#else
avpicture_fill( (AVPicture *)tmp_opicture,
tmp_opicture_buf, pf, c->width, c->height );
tmp_opicture_buf, pf, codec_context->width, codec_context->height );
#endif
}
}
Expand All @@ -375,7 +382,12 @@ void VideoStream::OpenStream( ) {
}

video_outbuf = NULL;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else
if ( !(of->flags & AVFMT_RAWPICTURE) ) {
#endif
/* allocate output buffer */
/* XXX: API change will be done */
// TODO: Make buffer dynamic.
Expand Down Expand Up @@ -446,6 +458,8 @@ VideoStream::VideoStream( const char *in_filename, const char *in_format, int bi
if ( pthread_mutex_init( buffer_copy_lock, NULL ) != 0 ) {
Fatal("pthread_mutex_init failed");
}

codec_context = NULL;
}

VideoStream::~VideoStream( ) {
Expand Down Expand Up @@ -481,7 +495,7 @@ VideoStream::~VideoStream( ) {

/* close each codec */
if ( ost ) {
avcodec_close( ost->codec );
avcodec_close( codec_context );
av_free( opicture->data[0] );
av_frame_free( &opicture );
if ( tmp_opicture ) {
Expand Down Expand Up @@ -564,17 +578,15 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
static struct SwsContext *img_convert_ctx = 0;
#endif // HAVE_LIBSWSCALE

AVCodecContext *c = ost->codec;

if ( c->pix_fmt != pf ) {
if ( codec_context->pix_fmt != pf ) {
memcpy( tmp_opicture->data[0], buffer, buffer_size );
#ifdef HAVE_LIBSWSCALE
if ( !img_convert_ctx ) {
img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
img_convert_ctx = sws_getCachedContext( NULL, codec_context->width, codec_context->height, pf, codec_context->width, codec_context->height, codec_context->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL );
if ( !img_convert_ctx )
Panic( "Unable to initialise image scaling context" );
}
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize );
sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, codec_context->height, opicture->data, opicture->linesize );
#else // HAVE_LIBSWSCALE
Fatal( "swscale is required for MPEG mode" );
#endif // HAVE_LIBSWSCALE
Expand All @@ -586,7 +598,13 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
AVPacket *pkt = packet_buffers[packet_index];
av_init_packet( pkt );
int got_packet = 0;
#if LIBAVFORMAT_VERSION_CHECK(57, 0, 0, 0, 0)
if (codec_context->codec_type == AVMEDIA_TYPE_VIDEO &&
codec_context->codec_id == AV_CODEC_ID_RAWVIDEO) {
#else
if ( of->flags & AVFMT_RAWPICTURE ) {
#endif

#if LIBAVCODEC_VERSION_CHECK(52, 30, 2, 30, 2)
pkt->flags |= AV_PKT_FLAG_KEY;
#else
Expand All @@ -597,19 +615,34 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
pkt->size = sizeof (AVPicture);
got_packet = 1;
} else {
opicture_ptr->pts = c->frame_number;
opicture_ptr->quality = c->global_quality;
opicture_ptr->pts = codec_context->frame_number;
opicture_ptr->quality = codec_context->global_quality;

#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
// Put encoder into flushing mode
avcodec_send_frame(codec_context, opicture_ptr);
int ret = avcodec_receive_packet(codec_context, pkt);
if ( ret < 0 ) {
if ( AVERROR_EOF != ret ) {
Error("ERror encoding video (%d) (%s)", ret,
av_err2str(ret));
}
} else {
got_packet = 1;
}
#else

#if LIBAVFORMAT_VERSION_CHECK(54, 1, 0, 2, 100)
int ret = avcodec_encode_video2( c, pkt, opicture_ptr, &got_packet );
int ret = avcodec_encode_video2( codec_context, pkt, opicture_ptr, &got_packet );
if ( ret != 0 ) {
Fatal( "avcodec_encode_video2 failed with errorcode %d \"%s\"", ret, av_err2str( ret ) );
}
#else
int out_size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, opicture_ptr );
int out_size = avcodec_encode_video( codec_context, video_outbuf, video_outbuf_size, opicture_ptr );
got_packet = out_size > 0 ? 1 : 0;
pkt->data = got_packet ? video_outbuf : NULL;
pkt->size = got_packet ? out_size : 0;
#endif
#endif
if ( got_packet ) {
// if ( c->coded_frame->key_frame )
Expand All @@ -622,12 +655,12 @@ double VideoStream::ActuallyEncodeFrame( const uint8_t *buffer, int buffer_size,
// }

if ( pkt->pts != (int64_t)AV_NOPTS_VALUE ) {
pkt->pts = av_rescale_q( pkt->pts, c->time_base, ost->time_base );
pkt->pts = av_rescale_q( pkt->pts, codec_context->time_base, ost->time_base );
}
if ( pkt->dts != (int64_t)AV_NOPTS_VALUE ) {
pkt->dts = av_rescale_q( pkt->dts, c->time_base, ost->time_base );
pkt->dts = av_rescale_q( pkt->dts, codec_context->time_base, ost->time_base );
}
pkt->duration = av_rescale_q( pkt->duration, c->time_base, ost->time_base );
pkt->duration = av_rescale_q( pkt->duration, codec_context->time_base, ost->time_base );
pkt->stream_index = ost->index;
}
}
Expand Down Expand Up @@ -658,8 +691,12 @@ void *VideoStream::StreamingThreadCallback(void *ctx){
VideoStream* videoStream = reinterpret_cast<VideoStream*>(ctx);

const uint64_t nanosecond_multiplier = 1000000000;

uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->ost->codec->time_base.num) / (videoStream->ost->codec->time_base.den) );

#if LIBAVCODEC_VERSION_CHECK(57, 64, 0, 64, 0)
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
#else
uint64_t target_interval_ns = nanosecond_multiplier * ( ((double)videoStream->codec_context->time_base.num) / (videoStream->codec_context->time_base.den) );
#endif
uint64_t frame_count = 0;
timespec start_time;
clock_gettime(CLOCK_MONOTONIC, &start_time);
Expand Down
1 change: 1 addition & 0 deletions src/zm_mpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class VideoStream
AVOutputFormat *of;
AVFormatContext *ofc;
AVStream *ost;
AVCodecContext *codec_context;
AVCodec *codec;
AVFrame *opicture;
AVFrame *tmp_opicture;
Expand Down
1 change: 1 addition & 0 deletions src/zm_remote_camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ int RemoteCamera::Read( int fd, char *buf, int size ) {
int bytes_to_recv = size - ReceivedBytes;
if ( SOCKET_BUF_SIZE < bytes_to_recv )
bytes_to_recv = SOCKET_BUF_SIZE;
//Debug(3, "Aiming to receive %d of %d bytes", bytes_to_recv, size );
bytes = recv(fd, &buf[ReceivedBytes], bytes_to_recv, 0); //socket, buffer, len, flags
if ( bytes <= 0 ) {
Error("RemoteCamera::Read Recv error. Closing Socket\n");
Expand Down
3 changes: 2 additions & 1 deletion src/zm_remote_camera.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ class RemoteCamera : public Camera {
virtual void Terminate() = 0;
virtual int Connect() = 0;
virtual int Disconnect() = 0;
virtual int PreCapture() = 0;
virtual int PreCapture() { return 0; };
virtual int PrimeCapture() { return 0; };
virtual int Capture( Image &image ) = 0;
virtual int PostCapture() = 0;
virtual int CaptureAndRecord( Image &image, timeval recording, char* event_directory )=0;
Expand Down

0 comments on commit e17bcb9

Please sign in to comment.