Files
fmviewer3/project/fm_viewer/fav/AVCompat.cpp
2026-02-21 17:11:31 +09:00

416 lines
14 KiB
C++

/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#include "AVCompat.h"
#include "version.h"
#if !FFMPEG_MODULE_CHECK(LIBAVFORMAT, 56, 4, 101)
int avio_feof(AVIOContext *s)
{
#if QTAV_USE_FFMPEG(LIBAVFORMAT)
return url_feof(s);
#else
return s && s->eof_reached;
#endif
}
#endif
#if QTAV_USE_LIBAV(LIBAVFORMAT)
int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat, const char *format, const char *filename)
{
AVFormatContext *s = avformat_alloc_context();
int ret = 0;
*avctx = NULL;
if (!s)
goto nomem;
if (!oformat) {
if (format) {
oformat = av_guess_format(format, NULL, NULL);
if (!oformat) {
av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format);
ret = AVERROR(EINVAL);
goto error;
}
} else {
oformat = av_guess_format(NULL, filename, NULL);
if (!oformat) {
ret = AVERROR(EINVAL);
av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n",
filename);
goto error;
}
}
}
s->oformat = oformat;
if (s->oformat->priv_data_size > 0) {
s->priv_data = av_mallocz(s->oformat->priv_data_size);
if (!s->priv_data)
goto nomem;
if (s->oformat->priv_class) {
*(const AVClass**)s->priv_data= s->oformat->priv_class;
av_opt_set_defaults(s->priv_data);
}
} else
s->priv_data = NULL;
if (filename)
av_strlcpy(s->filename, filename, sizeof(s->filename));
*avctx = s;
return 0;
nomem:
av_log(s, AV_LOG_ERROR, "Out of memory\n");
ret = AVERROR(ENOMEM);
error:
avformat_free_context(s);
return ret;
}
#endif //QTAV_USE_LIBAV(LIBAVFORMAT)
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 32, 0)
static const struct {
const char *name;
int nb_channels;
uint64_t layout;
} channel_layout_map[] = {
{ "mono", 1, AV_CH_LAYOUT_MONO },
{ "stereo", 2, AV_CH_LAYOUT_STEREO },
{ "4.0", 4, AV_CH_LAYOUT_4POINT0 },
{ "quad", 4, AV_CH_LAYOUT_QUAD },
{ "5.0", 5, AV_CH_LAYOUT_5POINT0 },
{ "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK },
{ "5.1", 6, AV_CH_LAYOUT_5POINT1 },
{ "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK },
{ "5.1+downmix", 8, AV_CH_LAYOUT_5POINT1|AV_CH_LAYOUT_STEREO_DOWNMIX, },
{ "7.1", 8, AV_CH_LAYOUT_7POINT1 },
{ "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE },
{ "7.1+downmix", 10, AV_CH_LAYOUT_7POINT1|AV_CH_LAYOUT_STEREO_DOWNMIX, },
{ 0 }
};
int64_t av_get_default_channel_layout(int nb_channels) {
int i;
for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++)
if (nb_channels == channel_layout_map[i].nb_channels)
return channel_layout_map[i].layout;
return 0;
}
#endif
/*
* always need this function if avresample available
* use AVAudioResampleContext to avoid func type confliction when swr is also available
*/
#if QTAV_HAVE(AVRESAMPLE)
AVAudioResampleContext *swr_alloc_set_opts(AVAudioResampleContext *s
, int64_t out_ch_layout
, enum AVSampleFormat out_sample_fmt
, int out_sample_rate
, int64_t in_ch_layout
, enum AVSampleFormat in_sample_fmt
, int in_sample_rate
, int log_offset, void *log_ctx)
{
//DO NOT use swr_alloc() because it's not defined as a macro in QtAV_Compat.h
if (!s)
s = avresample_alloc_context();
if (!s)
return 0;
Q_UNUSED(log_offset);
Q_UNUSED(log_ctx);
av_opt_set_int(s, "out_channel_layout", out_ch_layout , 0);
av_opt_set_int(s, "out_sample_fmt" , out_sample_fmt , 0);
av_opt_set_int(s, "out_sample_rate" , out_sample_rate, 0);
av_opt_set_int(s, "in_channel_layout" , in_ch_layout , 0);
av_opt_set_int(s, "in_sample_fmt" , in_sample_fmt , 0);
av_opt_set_int(s, "in_sample_rate" , in_sample_rate , 0);
return s;
}
#endif
#if !AV_MODULE_CHECK(LIBAVUTIL, 52, 3, 0, 13, 100)
extern const AVPixFmtDescriptor av_pix_fmt_descriptors[];
const AVPixFmtDescriptor *av_pix_fmt_desc_get(AVPixelFormat pix_fmt)
{
if (pix_fmt < 0 || pix_fmt >= QTAV_PIX_FMT_C(NB))
return NULL;
return &av_pix_fmt_descriptors[pix_fmt];
}
const AVPixFmtDescriptor *av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev)
{
if (!prev)
return &av_pix_fmt_descriptors[0];
// can not use sizeof(av_pix_fmt_descriptors)
while (prev - av_pix_fmt_descriptors < QTAV_PIX_FMT_C(NB) - 1) {
prev++;
if (prev->name)
return prev;
}
return NULL;
}
AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc)
{
if (desc < av_pix_fmt_descriptors ||
desc >= av_pix_fmt_descriptors + QTAV_PIX_FMT_C(NB))
return QTAV_PIX_FMT_C(NONE);
return AVPixelFormat(desc - av_pix_fmt_descriptors);
}
#endif // !AV_MODULE_CHECK(LIBAVUTIL, 52, 3, 0, 13, 100)
#if !FFMPEG_MODULE_CHECK(LIBAVUTIL, 52, 48, 101)
enum AVColorSpace av_frame_get_colorspace(const AVFrame *frame)
{
if (!frame)
return AVCOL_SPC_NB;
#if LIBAV_MODULE_CHECK(LIBAVUTIL, 53, 16, 0) //8c02adc
return frame->colorspace;
#endif
return AVCOL_SPC_NB;
}
enum AVColorRange av_frame_get_color_range(const AVFrame *frame)
{
if (!frame)
return AVCOL_RANGE_UNSPECIFIED;
#if LIBAV_MODULE_CHECK(LIBAVUTIL, 53, 16, 0) //8c02adc
return frame->color_range;
#endif
return AVCOL_RANGE_UNSPECIFIED;
}
#endif //!FFMPEG_MODULE_CHECK(LIBAVUTIL, 52, 28, 101)
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(52, 38, 100)
int av_pix_fmt_count_planes(AVPixelFormat pix_fmt)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
int i, planes[4] = { 0 }, ret = 0;
if (!desc)
return AVERROR(EINVAL);
for (i = 0; i < desc->nb_components; i++)
planes[desc->comp[i].plane] = 1;
for (i = 0; i < (int)FF_ARRAY_ELEMS(planes); i++)
ret += planes[i];
return ret;
}
#endif //AV_VERSION_INT(52, 38, 100)
#if LIBAVUTIL_VERSION_INT < AV_VERSION_INT(51, 73, 101)
int av_samples_copy(uint8_t **dst, uint8_t * const *src, int dst_offset,
int src_offset, int nb_samples, int nb_channels,
enum AVSampleFormat sample_fmt)
{
int planar = av_sample_fmt_is_planar(sample_fmt);
int planes = planar ? nb_channels : 1;
int block_align = av_get_bytes_per_sample(sample_fmt) * (planar ? 1 : nb_channels);
int data_size = nb_samples * block_align;
int i;
dst_offset *= block_align;
src_offset *= block_align;
if((dst[0] < src[0] ? src[0] - dst[0] : dst[0] - src[0]) >= data_size) {
for (i = 0; i < planes; i++)
memcpy(dst[i] + dst_offset, src[i] + src_offset, data_size);
} else {
for (i = 0; i < planes; i++)
memmove(dst[i] + dst_offset, src[i] + src_offset, data_size);
}
return 0;
}
#endif //AV_VERSION_INT(51, 73, 101)
#if QTAV_USE_LIBAV(LIBAVCODEC)
const char *avcodec_get_name(enum AVCodecID id)
{
const AVCodecDescriptor *cd;
AVCodec *codec;
if (id == AV_CODEC_ID_NONE)
return "none";
cd = avcodec_descriptor_get(id);
if (cd)
return cd->name;
av_log(NULL, AV_LOG_WARNING, "Codec 0x%x is not in the full list.\n", id);
codec = avcodec_find_decoder(id);
if (codec)
return codec->name;
codec = avcodec_find_encoder(id);
if (codec)
return codec->name;
return "unknown_codec";
}
#endif
#if !AV_MODULE_CHECK(LIBAVCODEC, 55, 55, 0, 68, 100)
void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
{
if (pkt->pts != (int64_t)AV_NOPTS_VALUE)
pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb);
if (pkt->dts != (int64_t)AV_NOPTS_VALUE)
pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb);
if (pkt->duration > 0)
pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb);
if (pkt->convergence_duration > 0)
pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb);
}
#endif
// since libav-11, ffmpeg-2.1
#if !LIBAV_MODULE_CHECK(LIBAVCODEC, 56, 1, 0) && !FFMPEG_MODULE_CHECK(LIBAVCODEC, 55, 39, 100)
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
{
dst->pts = src->pts;
dst->dts = src->dts;
dst->pos = src->pos;
dst->duration = src->duration;
dst->convergence_duration = src->convergence_duration;
dst->flags = src->flags;
dst->stream_index = src->stream_index;
for (int i = 0; i < src->side_data_elems; i++) {
enum AVPacketSideDataType type = src->side_data[i].type;
int size = src->side_data[i].size;
uint8_t *src_data = src->side_data[i].data;
uint8_t *dst_data = av_packet_new_side_data(dst, type, size);
if (!dst_data) {
av_packet_free_side_data(dst);
return AVERROR(ENOMEM);
}
memcpy(dst_data, src_data, size);
}
return 0;
}
#endif
// since libav-10, ffmpeg-2.1
#if !LIBAV_MODULE_CHECK(LIBAVCODEC, 55, 34, 1) && !FFMPEG_MODULE_CHECK(LIBAVCODEC, 55, 39, 100)
void av_packet_free_side_data(AVPacket *pkt)
{
for (int i = 0; i < pkt->side_data_elems; ++i)
av_freep(&pkt->side_data[i].data);
av_freep(&pkt->side_data);
pkt->side_data_elems = 0;
}
#endif
#if !AV_MODULE_CHECK(LIBAVCODEC, 55, 34, 1, 39, 101)
int av_packet_ref(AVPacket *dst, const AVPacket *src)
{
#if QTAV_USE_FFMPEG(LIBAVCODEC)
return av_copy_packet(dst, const_cast<AVPacket*>(src)); // not const in these versions
#else // libav <=11 has no av_copy_packet
#define DUP_DATA(dst, src, size, padding) \
do { \
void *data; \
if (padding) { \
if ((unsigned)(size) > \
(unsigned)(size) + FF_INPUT_BUFFER_PADDING_SIZE) \
goto failed_alloc; \
data = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); \
} else { \
data = av_malloc(size); \
} \
if (!data) \
goto failed_alloc; \
memcpy(data, src, size); \
if (padding) \
memset((uint8_t*)data + size, 0, \
FF_INPUT_BUFFER_PADDING_SIZE); \
*((void**)&dst) = data; \
} while (0)
*dst = *src;
dst->data = NULL;
dst->side_data = NULL;
DUP_DATA(dst->data, src->data, dst->size, 1);
dst->destruct = av_destruct_packet;
if (dst->side_data_elems) {
int i;
DUP_DATA(dst->side_data, src->side_data,
dst->side_data_elems * sizeof(*dst->side_data), 0);
memset(dst->side_data, 0,
dst->side_data_elems * sizeof(*dst->side_data));
for (i = 0; i < dst->side_data_elems; i++) {
DUP_DATA(dst->side_data[i].data, src->side_data[i].data, src->side_data[i].size, 1);
dst->side_data[i].size = src->side_data[i].size;
dst->side_data[i].type = src->side_data[i].type;
}
}
return 0;
failed_alloc:
av_destruct_packet(dst);
return AVERROR(ENOMEM);
#endif
}
#endif
#if !AV_MODULE_CHECK(LIBAVCODEC, 55, 52, 0, 63, 100)
void avcodec_free_context(AVCodecContext **pavctx)
{
AVCodecContext *avctx = *pavctx;
if (!avctx)
return;
avcodec_close(avctx);
av_freep(&avctx->extradata);
av_freep(&avctx->subtitle_header);
av_freep(&avctx->intra_matrix);
av_freep(&avctx->inter_matrix);
av_freep(&avctx->rc_override);
av_freep(pavctx);
}
#endif
const char *get_codec_long_name(enum AVCodecID id)
{
if (id == AV_CODEC_ID_NONE)
return "none";
const AVCodecDescriptor *cd = avcodec_descriptor_get(id);
if (cd)
return cd->long_name;
av_log(NULL, AV_LOG_WARNING, "Codec 0x%x is not in the full list.\n", id);
AVCodec *codec = avcodec_find_decoder(id);
if (codec)
return codec->long_name;
codec = avcodec_find_encoder(id);
if (codec)
return codec->long_name;
return "unknown_codec";
}
#if QTAV_HAVE(AVFILTER)
#if !AV_MODULE_CHECK(LIBAVFILTER, 2, 22, 0, 79, 100) //FF_API_AVFILTERPAD_PUBLIC
const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx)
{
return pads[pad_idx].name;
}
enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx)
{
return pads[pad_idx].type;
}
#endif
#endif //QTAV_HAVE(AVFILTER)