242 lines
8.4 KiB
C++
242 lines
8.4 KiB
C++
/*
|
|
* ZoneMinder FFMPEG Interface, $Date$, $Revision$
|
|
* Copyright (C) 2001-2008 Philip Coombes
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifndef ZM_FFMPEG_H
|
|
#define ZM_FFMPEG_H
|
|
|
|
#include "zm_config.h"
|
|
#include "zm_define.h"
|
|
|
|
extern "C" {
|
|
#include <libswresample/swresample.h>
|
|
|
|
// AVUTIL
|
|
#include <libavutil/avassert.h>
|
|
#include <libavutil/avutil.h>
|
|
#include <libavutil/base64.h>
|
|
#include <libavutil/mathematics.h>
|
|
#include <libavutil/avstring.h>
|
|
#include <libavutil/audio_fifo.h>
|
|
#include <libavutil/imgutils.h>
|
|
#include <libavutil/opt.h>
|
|
#if HAVE_LIBAVUTIL_HWCONTEXT_H
|
|
#include <libavutil/hwcontext.h>
|
|
#endif
|
|
|
|
/* LIBAVUTIL_VERSION_CHECK checks for the right version of libav and FFmpeg
|
|
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
|
* a is the major version
|
|
* b and c the minor and micro versions of libav
|
|
* d and e the minor and micro versions of FFmpeg */
|
|
#define LIBAVUTIL_VERSION_CHECK(a, b, c, d, e) \
|
|
( (LIBAVUTIL_VERSION_MICRO < 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \
|
|
(LIBAVUTIL_VERSION_MICRO >= 100 && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(a, d, e) ) )
|
|
|
|
#define _AVPIXELFORMAT AVPixelFormat
|
|
|
|
// AVCODEC
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
/*
|
|
* LIBAVCODEC_VERSION_CHECK checks for the right version of libav and FFmpeg
|
|
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
|
* a is the major version
|
|
* b and c the minor and micro versions of libav
|
|
* d and e the minor and micro versions of FFmpeg */
|
|
#define LIBAVCODEC_VERSION_CHECK(a, b, c, d, e) \
|
|
( (LIBAVCODEC_VERSION_MICRO < 100 && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \
|
|
(LIBAVCODEC_VERSION_MICRO >= 100 && LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(a, d, e) ) )
|
|
|
|
#define _AVCODECID AVCodecID
|
|
|
|
// AVFORMAT
|
|
#include <libavformat/avformat.h>
|
|
|
|
/* LIBAVFORMAT_VERSION_CHECK checks for the right version of libav and FFmpeg
|
|
* The original source is vlc (in modules/codec/avcodec/avcommon_compat.h)
|
|
* a is the major version
|
|
* b and c the minor and micro versions of libav
|
|
* d and e the minor and micro versions of FFmpeg */
|
|
#define LIBAVFORMAT_VERSION_CHECK(a, b, c, d, e) \
|
|
( (LIBAVFORMAT_VERSION_MICRO < 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \
|
|
(LIBAVFORMAT_VERSION_MICRO >= 100 && LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(a, d, e) ) )
|
|
|
|
// SWSCALE
|
|
#include <libswscale/swscale.h>
|
|
|
|
/* LIBSWSCALE_VERSION_CHECK checks for the right version of libav and FFmpeg
|
|
* a is the major version
|
|
* b and c the minor and micro versions of libav
|
|
* d and e the minor and micro versions of FFmpeg */
|
|
#define LIBSWSCALE_VERSION_CHECK(a, b, c, d, e) \
|
|
( (LIBSWSCALE_VERSION_MICRO < 100 && LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(a, b, c) ) || \
|
|
(LIBSWSCALE_VERSION_MICRO >= 100 && LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(a, d, e) ) )
|
|
|
|
}
|
|
|
|
/* A single function to initialize ffmpeg, to avoid multiple initializations */
|
|
void FFMPEGInit();
|
|
void FFMPEGDeInit();
|
|
|
|
enum _AVPIXELFORMAT GetFFMPEGPixelFormat(unsigned int p_colours, unsigned p_subpixelorder);
|
|
|
|
/*
|
|
* Some versions of libav does not contain this definition.
|
|
*/
|
|
#ifndef AV_ERROR_MAX_STRING_SIZE
|
|
#define AV_ERROR_MAX_STRING_SIZE 64
|
|
#endif
|
|
|
|
/*
|
|
* C++ friendly version of av_err2str taken from http://libav-users.943685.n4.nabble.com/Libav-user-g-4-7-2-fails-to-compile-av-err2str-td4656417.html.
|
|
* Newer g++ versions fail with "error: taking address of temporary array" when using native libav version.
|
|
*/
|
|
inline static const std::string av_make_error_string(int errnum) {
|
|
static char errbuf[AV_ERROR_MAX_STRING_SIZE];
|
|
av_strerror(errnum, errbuf, AV_ERROR_MAX_STRING_SIZE);
|
|
return (std::string)errbuf;
|
|
}
|
|
|
|
#undef av_err2str
|
|
#define av_err2str(errnum) av_make_error_string(errnum).c_str()
|
|
|
|
#ifndef av_rescale_delta
|
|
/**
|
|
* Rescale a timestamp while preserving known durations.
|
|
*/
|
|
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb);
|
|
#endif
|
|
|
|
#ifndef av_clip64
|
|
/**
|
|
* Clip a signed 64bit integer value into the amin-amax range.
|
|
* @param a value to clip
|
|
* @param amin minimum value of the clip range
|
|
* @param amax maximum value of the clip range
|
|
* @return clipped value
|
|
*/
|
|
static av_always_inline av_const int64_t av_clip64_c(int64_t a, int64_t amin, int64_t amax)
|
|
{
|
|
if (a < amin) return amin;
|
|
else if (a > amax) return amax;
|
|
else return a;
|
|
}
|
|
|
|
#define av_clip64 av_clip64_c
|
|
#endif
|
|
|
|
void zm_dump_stream_format(AVFormatContext *ic, int i, int index, int is_output);
|
|
void zm_dump_codec(const AVCodecContext *codec);
|
|
void zm_dump_codecpar(const AVCodecParameters *par);
|
|
|
|
#define zm_dump_frame(frame, text) Debug(1, "%s: format %d %s sample_rate %" PRIu32 " nb_samples %d" \
|
|
" layout %" PRIu64 " pts %" PRId64, \
|
|
text, \
|
|
frame->format, \
|
|
av_get_sample_fmt_name((AVSampleFormat)frame->format), \
|
|
frame->sample_rate, \
|
|
frame->nb_samples, \
|
|
frame->channel_layout, \
|
|
frame->pts \
|
|
);
|
|
|
|
#define zm_dump_video_frame(frame, text) Debug(1, "%s: format %d %s %dx%d linesize:%dx%d pts: %" PRId64 " keyframe: %d", \
|
|
text, \
|
|
frame->format, \
|
|
av_get_pix_fmt_name((AVPixelFormat)frame->format), \
|
|
frame->width, \
|
|
frame->height, \
|
|
frame->linesize[0], frame->linesize[1], \
|
|
frame->pts, \
|
|
frame->key_frame \
|
|
);
|
|
|
|
# define AV_PACKET_DURATION_FMT PRId64
|
|
|
|
#define CODEC_TYPE(stream) stream->codecpar->codec_type
|
|
#define CODEC(stream) stream->codecpar
|
|
|
|
#ifndef DBG_OFF
|
|
# define ZM_DUMP_PACKET(pkt, text) \
|
|
Debug(2, "%s: pts: %" PRId64 ", dts: %" PRId64 \
|
|
", size: %d, stream_index: %d, flags: %04x, keyframe(%d) pos: %" PRId64 ", duration: %" AV_PACKET_DURATION_FMT, \
|
|
text,\
|
|
pkt.pts,\
|
|
pkt.dts,\
|
|
pkt.size,\
|
|
pkt.stream_index,\
|
|
pkt.flags,\
|
|
pkt.flags & AV_PKT_FLAG_KEY,\
|
|
pkt.pos,\
|
|
pkt.duration)
|
|
|
|
# define ZM_DUMP_STREAM_PACKET(stream, pkt, text) \
|
|
if (logDebugging()) { \
|
|
double pts_time = static_cast<double>(av_rescale_q(pkt.pts, stream->time_base, AV_TIME_BASE_Q)) / AV_TIME_BASE; \
|
|
\
|
|
Debug(2, "%s: pts: %" PRId64 " * %u/%u=%f, dts: %" PRId64 \
|
|
", size: %d, stream_index: %d, %s flags: %04x, keyframe(%d) pos: %" PRId64", duration: %" AV_PACKET_DURATION_FMT, \
|
|
text, \
|
|
pkt.pts, \
|
|
stream->time_base.num, \
|
|
stream->time_base.den, \
|
|
pts_time, \
|
|
pkt.dts, \
|
|
pkt.size, \
|
|
pkt.stream_index, \
|
|
av_get_media_type_string(CODEC_TYPE(stream)), \
|
|
pkt.flags, \
|
|
pkt.flags & AV_PKT_FLAG_KEY, \
|
|
pkt.pos, \
|
|
pkt.duration); \
|
|
}
|
|
|
|
#else
|
|
# define ZM_DUMP_PACKET(pkt, text)
|
|
# define ZM_DUMP_STREAM_PACKET(stream, pkt, text)
|
|
#endif
|
|
|
|
#define zm_av_packet_unref(packet) av_packet_unref(packet)
|
|
#define zm_av_packet_ref(dst, src) av_packet_ref(dst, src)
|
|
|
|
#define zm_av_frame_alloc() av_frame_alloc()
|
|
|
|
int check_sample_fmt(AVCodec *codec, enum AVSampleFormat sample_fmt);
|
|
enum AVPixelFormat fix_deprecated_pix_fmt(enum AVPixelFormat );
|
|
|
|
bool is_video_stream(const AVStream *);
|
|
bool is_audio_stream(const AVStream *);
|
|
bool is_video_context(const AVCodec *);
|
|
bool is_audio_context(const AVCodec *);
|
|
|
|
int zm_receive_packet(AVCodecContext *context, AVPacket &packet);
|
|
|
|
int zm_send_packet_receive_frame(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
|
|
int zm_send_frame_receive_packet(AVCodecContext *context, AVFrame *frame, AVPacket &packet);
|
|
|
|
void zm_packet_copy_rescale_ts(const AVPacket *ipkt, AVPacket *opkt, const AVRational src_tb, const AVRational dst_tb);
|
|
|
|
int zm_resample_audio(SwrContext *resample_ctx, AVFrame *in_frame, AVFrame *out_frame);
|
|
int zm_resample_get_delay(SwrContext *resample_ctx, int time_base);
|
|
|
|
int zm_add_samples_to_fifo(AVAudioFifo *fifo, AVFrame *frame);
|
|
int zm_get_samples_from_fifo(AVAudioFifo *fifo, AVFrame *frame);
|
|
|
|
#endif // ZM_FFMPEG_H
|