- switch from indent to clang-format, which is supported by Visual Studio Code

- reindent all sources to common code style
- fix include sort errors from clang-format
- update AGPL 3.0 license file
This commit is contained in:
Dirk Nehring
2021-12-27 20:02:45 +01:00
parent 987ff6ba12
commit 177e44de98
29 changed files with 4309 additions and 5337 deletions

405
codec.c
View File

@@ -1,7 +1,7 @@
///
/// @file codec.c @brief Codec functions
///
/// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -27,7 +27,7 @@
/// It is uses ffmpeg (http://ffmpeg.org) as backend.
///
/// It may work with libav (http://libav.org), but the tests show
/// many bugs and incompatiblity in it. Don't use this shit.
/// many bugs and incompatiblity in it. Don't use this shit.
///
/// compile with pass-through support (stable, AC-3, E-AC-3 only)
@@ -51,16 +51,16 @@
#include <endian.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libintl.h>
#define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut
#include <sys/stat.h>
#include <sys/types.h>
#define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/mem.h>
#include <libavutil/opt.h>
#ifdef USE_SWRESAMPLE
#include <libswresample/swresample.h>
@@ -75,11 +75,13 @@
#endif
#include <pthread.h>
// clang-format off
#include "iatomic.h"
#include "misc.h"
#include "video.h"
#include "audio.h"
#include "codec.h"
// clang-format on
//----------------------------------------------------------------------------
// Global
@@ -113,12 +115,12 @@ AVBufferRef *hw_device_ctx;
///
struct _video_decoder_
{
VideoHwDecoder *HwDecoder; ///< video hardware decoder
VideoHwDecoder *HwDecoder; ///< video hardware decoder
int GetFormatDone; ///< flag get format called!
AVCodec *VideoCodec; ///< video codec
AVCodecContext *VideoCtx; ///< video codec context
AVFrame *Frame; ///< decoded video frame
int GetFormatDone; ///< flag get format called!
AVCodec *VideoCodec; ///< video codec
AVCodecContext *VideoCtx; ///< video codec context
AVFrame *Frame; ///< decoded video frame
};
#endif
//----------------------------------------------------------------------------
@@ -128,14 +130,13 @@ struct _video_decoder_
/**
** Callback to negotiate the PixelFormat.
**
** @param video_ctx codec context
** @param fmt is the list of formats which are supported by
** the codec, it is terminated by -1 as 0 is a
** valid format, the formats are ordered by
** quality.
** @param video_ctx codec context
** @param fmt is the list of formats which are supported by
** the codec, it is terminated by -1 as 0 is a
** valid format, the formats are ordered by
** quality.
*/
static enum AVPixelFormat Codec_get_format(AVCodecContext * video_ctx, const enum AVPixelFormat *fmt)
{
static enum AVPixelFormat Codec_get_format(AVCodecContext *video_ctx, const enum AVPixelFormat *fmt) {
VideoDecoder *decoder;
enum AVPixelFormat fmt1;
@@ -145,9 +146,8 @@ static enum AVPixelFormat Codec_get_format(AVCodecContext * video_ctx, const enu
Error("codec/video: ffmpeg/libav buggy: width or height zero\n");
}
// decoder->GetFormatDone = 1;
// decoder->GetFormatDone = 1;
return Video_get_format(decoder->HwDecoder, video_ctx, fmt);
}
// static void Codec_free_buffer(void *opaque, uint8_t *data);
@@ -157,16 +157,15 @@ static enum AVPixelFormat Codec_get_format(AVCodecContext * video_ctx, const enu
**
** Called at the beginning of each frame to get a buffer for it.
**
** @param video_ctx Codec context
** @param frame Get buffer for this frame
** @param video_ctx Codec context
** @param frame Get buffer for this frame
*/
static int Codec_get_buffer2(AVCodecContext * video_ctx, AVFrame * frame, int flags)
{
static int Codec_get_buffer2(AVCodecContext *video_ctx, AVFrame *frame, int flags) {
VideoDecoder *decoder;
decoder = video_ctx->opaque;
if (!decoder->GetFormatDone) { // get_format missing
if (!decoder->GetFormatDone) { // get_format missing
enum AVPixelFormat fmts[2];
// fprintf(stderr, "codec: buggy libav, use ffmpeg\n");
@@ -177,9 +176,9 @@ static int Codec_get_buffer2(AVCodecContext * video_ctx, AVFrame * frame, int fl
}
#if 0
if (decoder->hwaccel_get_buffer && (AV_PIX_FMT_VDPAU == decoder->hwaccel_pix_fmt
|| AV_PIX_FMT_CUDA == decoder->hwaccel_pix_fmt || AV_PIX_FMT_VAAPI == decoder->hwaccel_pix_fmt)) {
// Debug(3,"hwaccel get_buffer\n");
return decoder->hwaccel_get_buffer(video_ctx, frame, flags);
|| AV_PIX_FMT_CUDA == decoder->hwaccel_pix_fmt || AV_PIX_FMT_VAAPI == decoder->hwaccel_pix_fmt)) {
// Debug(3,"hwaccel get_buffer\n");
return decoder->hwaccel_get_buffer(video_ctx, frame, flags);
}
#endif
// Debug(3, "codec: fallback to default get_buffer\n");
@@ -193,12 +192,11 @@ static int Codec_get_buffer2(AVCodecContext * video_ctx, AVFrame * frame, int fl
/**
** Allocate a new video decoder context.
**
** @param hw_decoder video hardware decoder
** @param hw_decoder video hardware decoder
**
** @returns private decoder pointer for video decoder.
*/
VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder)
{
VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *hw_decoder) {
VideoDecoder *decoder;
if (!(decoder = calloc(1, sizeof(*decoder)))) {
@@ -214,10 +212,7 @@ VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder * hw_decoder)
**
** @param decoder private video decoder
*/
void CodecVideoDelDecoder(VideoDecoder * decoder)
{
free(decoder);
}
void CodecVideoDelDecoder(VideoDecoder *decoder) { free(decoder); }
/**
** Open video decoder.
@@ -225,14 +220,13 @@ void CodecVideoDelDecoder(VideoDecoder * decoder)
** @param decoder private video decoder
** @param codec_id video codec id
*/
void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
{
void CodecVideoOpen(VideoDecoder *decoder, int codec_id) {
AVCodec *video_codec;
const char *name;
int ret, deint = 2;
Debug(3, "***************codec: Video Open using video codec ID %#06x (%s)\n", codec_id,
avcodec_get_name(codec_id));
avcodec_get_name(codec_id));
if (decoder->VideoCtx) {
Error(_("codec: missing close\n"));
@@ -261,7 +255,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
break;
case AV_CODEC_ID_H264:
name = "h264_v4l2m2m";
// name = "h264_mmal";
// name = "h264_mmal";
break;
case AV_CODEC_ID_HEVC:
name = "hevc_v4l2m2m";
@@ -289,8 +283,9 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
}
decoder->VideoCtx->hw_device_ctx = av_buffer_ref(HwDeviceContext);
#else
decoder->VideoCtx->pix_fmt = AV_PIX_FMT_DRM_PRIME; /* request a DRM frame */
// decoder->VideoCtx->pix_fmt = AV_PIX_FMT_MMAL; /* request a DRM frame */
decoder->VideoCtx->pix_fmt = AV_PIX_FMT_DRM_PRIME; /* request a DRM frame */
// decoder->VideoCtx->pix_fmt = AV_PIX_FMT_MMAL; /* request a DRM frame
//*/
#endif
// FIXME: for software decoder use all cpus, otherwise 1
@@ -310,12 +305,12 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
// decoder->VideoCtx->extra_hw_frames = 8; // VIDEO_SURFACES_MAX +1
if (video_codec->capabilities & (AV_CODEC_CAP_AUTO_THREADS)) {
Debug(3, "codec: auto threads enabled");
// decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_count = 0;
}
if (video_codec->capabilities & AV_CODEC_CAP_TRUNCATED) {
Debug(3, "codec: supports truncated packets");
//decoder->VideoCtx->flags |= CODEC_FLAG_TRUNCATED;
// decoder->VideoCtx->flags |= CODEC_FLAG_TRUNCATED;
}
// FIXME: own memory management for video frames.
if (video_codec->capabilities & AV_CODEC_CAP_DR1) {
@@ -323,16 +318,16 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
}
if (video_codec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
Debug(3, "codec: supports frame threads");
// decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_type |= FF_THREAD_FRAME;
}
if (video_codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
Debug(3, "codec: supports slice threads");
// decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_count = 0;
// decoder->VideoCtx->thread_type |= FF_THREAD_SLICE;
}
// if (av_opt_set_int(decoder->VideoCtx, "refcounted_frames", 1, 0) < 0)
// Fatal(_("VAAPI Refcounts invalid\n"));
// if (av_opt_set_int(decoder->VideoCtx, "refcounted_frames", 1, 0) < 0)
// Fatal(_("VAAPI Refcounts invalid\n"));
decoder->VideoCtx->thread_safe_callbacks = 0;
#endif
@@ -352,8 +347,9 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
#endif
#ifdef CUVID
if (strcmp(decoder->VideoCodec->long_name, "Nvidia CUVID MPEG2VIDEO decoder") == 0) { // deinterlace for mpeg2 is somehow broken
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", deint, 0) < 0) { // adaptive
if (strcmp(decoder->VideoCodec->long_name,
"Nvidia CUVID MPEG2VIDEO decoder") == 0) { // deinterlace for mpeg2 is somehow broken
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", deint, 0) < 0) { // adaptive
pthread_mutex_unlock(&CodecLockMutex);
Fatal(_("codec: can't set option deint to video codec!\n"));
}
@@ -368,7 +364,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
Fatal(_("codec: can't set option drop 2.field to video codec!\n"));
}
} else if (strstr(decoder->VideoCodec->long_name, "Nvidia CUVID") != NULL) {
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", deint, 0) < 0) { // adaptive
if (av_opt_set_int(decoder->VideoCtx->priv_data, "deint", deint, 0) < 0) { // adaptive
pthread_mutex_unlock(&CodecLockMutex);
Fatal(_("codec: can't set option deint to video codec!\n"));
}
@@ -393,12 +389,12 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
pthread_mutex_unlock(&CodecLockMutex);
decoder->VideoCtx->opaque = decoder; // our structure
decoder->VideoCtx->opaque = decoder; // our structure
//decoder->VideoCtx->debug = FF_DEBUG_STARTCODE;
//decoder->VideoCtx->err_recognition |= AV_EF_EXPLODE;
// decoder->VideoCtx->debug = FF_DEBUG_STARTCODE;
// decoder->VideoCtx->err_recognition |= AV_EF_EXPLODE;
//av_log_set_level(AV_LOG_DEBUG);
// av_log_set_level(AV_LOG_DEBUG);
av_log_set_level(0);
decoder->VideoCtx->get_format = Codec_get_format;
@@ -408,17 +404,17 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
decoder->VideoCtx->hwaccel_context = VideoGetHwAccelContext(decoder->HwDecoder);
//
// Prepare frame buffer for decoder
// Prepare frame buffer for decoder
//
#if 0
if (!(decoder->Frame = av_frame_alloc())) {
Fatal(_("codec: can't allocate video decoder frame buffer\n"));
Fatal(_("codec: can't allocate video decoder frame buffer\n"));
}
#endif
// reset buggy ffmpeg/libav flag
decoder->GetFormatDone = 0;
#if defined (YADIF) || defined (RASPI)
#if defined(YADIF) || defined(RASPI)
decoder->filter = 0;
#endif
}
@@ -428,8 +424,7 @@ void CodecVideoOpen(VideoDecoder * decoder, int codec_id)
**
** @param video_decoder private video decoder
*/
void CodecVideoClose(VideoDecoder * video_decoder)
{
void CodecVideoClose(VideoDecoder *video_decoder) {
AVFrame *frame;
// FIXME: play buffered data
@@ -441,14 +436,14 @@ void CodecVideoClose(VideoDecoder * video_decoder)
#if 1
frame = av_frame_alloc();
avcodec_send_packet(video_decoder->VideoCtx, NULL);
while (avcodec_receive_frame(video_decoder->VideoCtx, frame) >= 0) ;
while (avcodec_receive_frame(video_decoder->VideoCtx, frame) >= 0)
;
av_frame_free(&frame);
#endif
avcodec_close(video_decoder->VideoCtx);
av_freep(&video_decoder->VideoCtx);
pthread_mutex_unlock(&CodecLockMutex);
}
}
#if 0
@@ -472,16 +467,16 @@ void DisplayPts(AVCodecContext * video_ctx, AVFrame * frame)
pts = frame->pkt_pts;
if (pts == (int64_t) AV_NOPTS_VALUE) {
printf("*");
printf("*");
}
ms_delay = (1000 * video_ctx->time_base.num) / video_ctx->time_base.den;
ms_delay += frame->repeat_pict * ms_delay / 2;
printf("codec: PTS %s%s %" PRId64 " %d %d/%d %d/%d %dms\n", frame->repeat_pict ? "r" : " ",
frame->interlaced_frame ? "I" : " ", pts, (int)(pts - last_pts) / 90, video_ctx->time_base.num,
video_ctx->time_base.den, video_ctx->framerate.num, video_ctx->framerate.den, ms_delay);
printf("codec: PTS %s%s %" PRId64 " %d %d/%d %d/%d %dms\n", frame->repeat_pict ? "r" : " ",
frame->interlaced_frame ? "I" : " ", pts, (int)(pts - last_pts) / 90, video_ctx->time_base.num,
video_ctx->time_base.den, video_ctx->framerate.num, video_ctx->framerate.den, ms_delay);
if (pts != (int64_t) AV_NOPTS_VALUE) {
last_pts = pts;
last_pts = pts;
}
}
@@ -495,14 +490,13 @@ void DisplayPts(AVCodecContext * video_ctx, AVFrame * frame)
*/
extern int CuvidTestSurfaces();
#if defined YADIF || defined (VAAPI)
extern int init_filters(AVCodecContext * dec_ctx, void *decoder, AVFrame * frame);
extern int push_filters(AVCodecContext * dec_ctx, void *decoder, AVFrame * frame);
#if defined YADIF || defined(VAAPI)
extern int init_filters(AVCodecContext *dec_ctx, void *decoder, AVFrame *frame);
extern int push_filters(AVCodecContext *dec_ctx, void *decoder, AVFrame *frame);
#endif
#ifdef VAAPI
void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
{
void CodecVideoDecode(VideoDecoder *decoder, const AVPacket *avpkt) {
AVCodecContext *video_ctx = decoder->VideoCtx;
if (video_ctx->codec_type == AVMEDIA_TYPE_VIDEO && CuvidTestSurfaces()) {
@@ -510,7 +504,7 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
AVPacket pkt[1];
AVFrame *frame;
*pkt = *avpkt; // use copy
*pkt = *avpkt; // use copy
ret = avcodec_send_packet(video_ctx, pkt);
if (ret < 0) {
return;
@@ -540,7 +534,8 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
decoder->filter = 2;
}
}
if (frame->interlaced_frame && decoder->filter == 2 && (frame->height != 720)) { // broken ZDF sends Interlaced flag
if (frame->interlaced_frame && decoder->filter == 2 &&
(frame->height != 720)) { // broken ZDF sends Interlaced flag
push_filters(video_ctx, decoder->HwDecoder, frame);
continue;
}
@@ -557,8 +552,7 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
#ifdef CUVID
void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
{
void CodecVideoDecode(VideoDecoder *decoder, const AVPacket *avpkt) {
AVCodecContext *video_ctx;
AVFrame *frame;
int ret, ret1;
@@ -567,10 +561,10 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
static uint64_t first_time = 0;
const AVPacket *pkt;
next_part:
next_part:
video_ctx = decoder->VideoCtx;
pkt = avpkt; // use copy
pkt = avpkt; // use copy
got_frame = 0;
// printf("decode packet %d\n",(GetusTicks()-first_time)/1000000);
@@ -585,21 +579,23 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
if (!CuvidTestSurfaces())
usleep(1000);
// printf("send packet to decode %s %04x\n",consumed?"ok":"Full",ret1);
// printf("send packet to decode %s %04x\n",consumed?"ok":"Full",ret1);
if ((ret1 == AVERROR(EAGAIN) || ret1 == AVERROR_EOF || ret1 >= 0) && CuvidTestSurfaces()) {
ret = 0;
while ((ret >= 0) && CuvidTestSurfaces()) { // get frames until empty snd Surfaces avail.
frame = av_frame_alloc();
ret = avcodec_receive_frame(video_ctx, frame); // get new frame
if (ret >= 0) { // one is avail.
ret = avcodec_receive_frame(video_ctx, frame); // get new frame
if (ret >= 0) { // one is avail.
got_frame = 1;
} else {
got_frame = 0;
}
// printf("got %s packet from decoder\n",got_frame?"1":"no");
if (got_frame) { // frame completed
// printf("video frame pts %#012" PRIx64 " %dms\n",frame->pts,(int)(apts - frame->pts) / 90);
// printf("got %s packet from
// decoder\n",got_frame?"1":"no");
if (got_frame) { // frame completed
// printf("video frame pts %#012" PRIx64 "
//%dms\n",frame->pts,(int)(apts - frame->pts) / 90);
#ifdef YADIF
if (decoder->filter) {
if (decoder->filter == 1) {
@@ -611,7 +607,8 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
decoder->filter = 2;
}
}
if (frame->interlaced_frame && decoder->filter == 2 && (frame->height != 720)) { // broken ZDF sends Interlaced flag
if (frame->interlaced_frame && decoder->filter == 2 &&
(frame->height != 720)) { // broken ZDF sends Interlaced flag
ret = push_filters(video_ctx, decoder->HwDecoder, frame);
// av_frame_unref(frame);
continue;
@@ -634,9 +631,8 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
}
if (!consumed) {
goto next_part; // try again to stuff decoder
goto next_part; // try again to stuff decoder
}
}
#endif
@@ -645,8 +641,7 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
**
** @param decoder video decoder data
*/
void CodecVideoFlushBuffers(VideoDecoder * decoder)
{
void CodecVideoFlushBuffers(VideoDecoder *decoder) {
if (decoder->VideoCtx) {
avcodec_flush_buffers(decoder->VideoCtx);
}
@@ -666,58 +661,56 @@ typedef struct _audio_decoder_ AudioDecoder;
///
/// Audio decoder structure.
///
struct _audio_decoder_
{
AVCodec *AudioCodec; ///< audio codec
AVCodecContext *AudioCtx; ///< audio codec context
struct _audio_decoder_ {
AVCodec *AudioCodec; ///< audio codec
AVCodecContext *AudioCtx; ///< audio codec context
char Passthrough; ///< current pass-through flags
int SampleRate; ///< current stream sample rate
int Channels; ///< current stream channels
char Passthrough; ///< current pass-through flags
int SampleRate; ///< current stream sample rate
int Channels; ///< current stream channels
int HwSampleRate; ///< hw sample rate
int HwChannels; ///< hw channels
int HwSampleRate; ///< hw sample rate
int HwChannels; ///< hw channels
AVFrame *Frame; ///< decoded audio frame buffer
AVFrame *Frame; ///< decoded audio frame buffer
#ifdef USE_SWRESAMPLE
#if LIBSWRESAMPLE_VERSION_INT < AV_VERSION_INT(0, 15, 100)
struct SwrContext *Resample; ///< ffmpeg software resample context
struct SwrContext *Resample; ///< ffmpeg software resample context
#else
SwrContext *Resample; ///< ffmpeg software resample context
SwrContext *Resample; ///< ffmpeg software resample context
#endif
#endif
#ifdef USE_AVRESAMPLE
AVAudioResampleContext *Resample; ///< libav software resample context
AVAudioResampleContext *Resample; ///< libav software resample context
#endif
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
int SpdifIndex; ///< index into SPDIF output buffer
int SpdifCount; ///< SPDIF repeat counter
uint16_t Spdif[24576 / 2]; ///< SPDIF output buffer
int SpdifIndex; ///< index into SPDIF output buffer
int SpdifCount; ///< SPDIF repeat counter
int64_t LastDelay; ///< last delay
struct timespec LastTime; ///< last time
int64_t LastPTS; ///< last PTS
int64_t LastDelay; ///< last delay
struct timespec LastTime; ///< last time
int64_t LastPTS; ///< last PTS
int Drift; ///< accumulated audio drift
int DriftCorr; ///< audio drift correction value
int DriftFrac; ///< audio drift fraction for ac3
int Drift; ///< accumulated audio drift
int DriftCorr; ///< audio drift correction value
int DriftFrac; ///< audio drift fraction for ac3
};
///
/// IEC Data type enumeration.
///
enum IEC61937
{
IEC61937_AC3 = 0x01, ///< AC-3 data
enum IEC61937 {
IEC61937_AC3 = 0x01, ///< AC-3 data
// FIXME: more data types
IEC61937_EAC3 = 0x15, ///< E-AC-3 data
IEC61937_EAC3 = 0x15, ///< E-AC-3 data
};
#ifdef USE_AUDIO_DRIFT_CORRECTION
#define CORRECT_PCM 1 ///< do PCM audio-drift correction
#define CORRECT_AC3 2 ///< do AC-3 audio-drift correction
static char CodecAudioDrift; ///< flag: enable audio-drift correction
#define CORRECT_PCM 1 ///< do PCM audio-drift correction
#define CORRECT_AC3 2 ///< do AC-3 audio-drift correction
static char CodecAudioDrift; ///< flag: enable audio-drift correction
#else
static const int CodecAudioDrift = 0;
#endif
@@ -729,15 +722,14 @@ static char CodecPassthrough;
#else
static const int CodecPassthrough = 0;
#endif
static char CodecDownmix; ///< enable AC-3 decoder downmix
static char CodecDownmix; ///< enable AC-3 decoder downmix
/**
** Allocate a new audio decoder context.
**
** @returns private decoder pointer for audio decoder.
*/
AudioDecoder *CodecAudioNewDecoder(void)
{
AudioDecoder *CodecAudioNewDecoder(void) {
AudioDecoder *audio_decoder;
if (!(audio_decoder = calloc(1, sizeof(*audio_decoder)))) {
@@ -755,9 +747,8 @@ AudioDecoder *CodecAudioNewDecoder(void)
**
** @param decoder private audio decoder
*/
void CodecAudioDelDecoder(AudioDecoder * decoder)
{
av_frame_free(&decoder->Frame); // callee does checks
void CodecAudioDelDecoder(AudioDecoder *decoder) {
av_frame_free(&decoder->Frame); // callee does checks
free(decoder);
}
@@ -767,8 +758,7 @@ void CodecAudioDelDecoder(AudioDecoder * decoder)
** @param audio_decoder private audio decoder
** @param codec_id audio codec id
*/
void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
{
void CodecAudioOpen(AudioDecoder *audio_decoder, int codec_id) {
AVCodec *audio_codec;
Debug(3, "codec: using audio codec ID %#06x (%s)\n", codec_id, avcodec_get_name(codec_id));
@@ -817,8 +807,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id)
**
** @param audio_decoder private audio decoder
*/
void CodecAudioClose(AudioDecoder * audio_decoder)
{
void CodecAudioClose(AudioDecoder *audio_decoder) {
// FIXME: output any buffered data
#ifdef USE_SWRESAMPLE
@@ -844,8 +833,7 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
**
** @param mask enable mask (PCM, AC-3)
*/
void CodecSetAudioDrift(int mask)
{
void CodecSetAudioDrift(int mask) {
#ifdef USE_AUDIO_DRIFT_CORRECTION
CodecAudioDrift = mask & (CORRECT_PCM | CORRECT_AC3);
#endif
@@ -857,8 +845,7 @@ void CodecSetAudioDrift(int mask)
**
** @param mask enable mask (PCM, AC-3, E-AC-3)
*/
void CodecSetAudioPassthrough(int mask)
{
void CodecSetAudioPassthrough(int mask) {
#ifdef USE_PASSTHROUGH
CodecPassthrough = mask & (CodecPCM | CodecAC3 | CodecEAC3);
#endif
@@ -870,8 +857,7 @@ void CodecSetAudioPassthrough(int mask)
**
** @param onoff enable/disable downmix.
*/
void CodecSetAudioDownmix(int onoff)
{
void CodecSetAudioDownmix(int onoff) {
if (onoff == -1) {
CodecDownmix ^= 1;
return;
@@ -882,16 +868,15 @@ void CodecSetAudioDownmix(int onoff)
/**
** Reorder audio frame.
**
** ffmpeg L R C Ls Rs -> alsa L R Ls Rs C
** ffmpeg L R C LFE Ls Rs -> alsa L R Ls Rs C LFE
** ffmpeg L R C LFE Ls Rs Rl Rr -> alsa L R Ls Rs C LFE Rl Rr
** ffmpeg L R C Ls Rs -> alsa L R Ls Rs C
** ffmpeg L R C LFE Ls Rs -> alsa L R Ls Rs C LFE
** ffmpeg L R C LFE Ls Rs Rl Rr -> alsa L R Ls Rs C LFE Rl Rr
**
** @param buf[IN,OUT] sample buffer
** @param size size of sample buffer in bytes
** @param channels number of channels interleaved in sample buffer
** @param buf[IN,OUT] sample buffer
** @param size size of sample buffer in bytes
** @param channels number of channels interleaved in sample buffer
*/
static void CodecReorderAudioFrame(int16_t * buf, int size, int channels)
{
static void CodecReorderAudioFrame(int16_t *buf, int size, int channels) {
int i;
int c;
int ls;
@@ -945,17 +930,16 @@ static void CodecReorderAudioFrame(int16_t * buf, int size, int channels)
** @param audio_decoder audio decoder data
** @param[out] passthrough pass-through output
*/
static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder, int *passthrough)
{
static int CodecAudioUpdateHelper(AudioDecoder *audio_decoder, int *passthrough) {
const AVCodecContext *audio_ctx;
int err;
audio_ctx = audio_decoder->AudioCtx;
Debug(3, "codec/audio: format change %s %dHz *%d channels%s%s%s%s%s\n",
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate, audio_ctx->channels,
CodecPassthrough & CodecPCM ? " PCM" : "", CodecPassthrough & CodecMPA ? " MPA" : "",
CodecPassthrough & CodecAC3 ? " AC-3" : "", CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
CodecPassthrough ? " pass-through" : "");
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate, audio_ctx->channels,
CodecPassthrough & CodecPCM ? " PCM" : "", CodecPassthrough & CodecMPA ? " MPA" : "",
CodecPassthrough & CodecAC3 ? " AC-3" : "", CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
CodecPassthrough ? " pass-through" : "");
*passthrough = 0;
audio_decoder->SampleRate = audio_ctx->sample_rate;
@@ -965,14 +949,14 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder, int *passthrough
audio_decoder->Passthrough = CodecPassthrough;
// SPDIF/HDMI pass-through
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3)
|| (CodecPassthrough & CodecEAC3 && audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) ||
(CodecPassthrough & CodecEAC3 && audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
// E-AC-3 over HDMI some receivers need HBR
audio_decoder->HwSampleRate *= 4;
}
audio_decoder->HwChannels = 2;
audio_decoder->SpdifIndex = 0; // reset buffer
audio_decoder->SpdifIndex = 0; // reset buffer
audio_decoder->SpdifCount = 0;
*passthrough = 1;
}
@@ -981,8 +965,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder, int *passthrough
// try E-AC-3 none HBR
audio_decoder->HwSampleRate /= 4;
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3
|| (err = AudioSetup(&audio_decoder->HwSampleRate, &audio_decoder->HwChannels, *passthrough))) {
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3 ||
(err = AudioSetup(&audio_decoder->HwSampleRate, &audio_decoder->HwChannels, *passthrough))) {
Debug(3, "codec/audio: audio setup error\n");
// FIXME: handle errors
@@ -993,8 +977,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder, int *passthrough
}
Debug(3, "codec/audio: resample %s %dHz *%d -> %s %dHz *%d\n", av_get_sample_fmt_name(audio_ctx->sample_fmt),
audio_ctx->sample_rate, audio_ctx->channels, av_get_sample_fmt_name(AV_SAMPLE_FMT_S16),
audio_decoder->HwSampleRate, audio_decoder->HwChannels);
audio_ctx->sample_rate, audio_ctx->channels, av_get_sample_fmt_name(AV_SAMPLE_FMT_S16),
audio_decoder->HwSampleRate, audio_decoder->HwChannels);
return 0;
}
@@ -1003,10 +987,9 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder, int *passthrough
** Audio pass-through decoder helper.
**
** @param audio_decoder audio decoder data
** @param avpkt undecoded audio packet
** @param avpkt undecoded audio packet
*/
static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPacket * avpkt)
{
static int CodecAudioPassthroughHelper(AudioDecoder *audio_decoder, const AVPacket *avpkt) {
#ifdef USE_PASSTHROUGH
const AVCodecContext *audio_ctx;
@@ -1025,14 +1008,13 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
if (CodecAudioDrift & CORRECT_AC3) {
int x;
x = (audio_decoder->DriftFrac +
(audio_decoder->DriftCorr * spdif_sz)) / (10 * audio_decoder->HwSampleRate * 100);
audio_decoder->DriftFrac =
(audio_decoder->DriftFrac +
(audio_decoder->DriftCorr * spdif_sz)) % (10 * audio_decoder->HwSampleRate * 100);
x = (audio_decoder->DriftFrac + (audio_decoder->DriftCorr * spdif_sz)) /
(10 * audio_decoder->HwSampleRate * 100);
audio_decoder->DriftFrac = (audio_decoder->DriftFrac + (audio_decoder->DriftCorr * spdif_sz)) %
(10 * audio_decoder->HwSampleRate * 100);
// round to word border
x *= audio_decoder->HwChannels * 4;
if (x < -64) { // limit correction
if (x < -64) { // limit correction
x = -64;
} else if (x > 64) {
x = 64;
@@ -1047,7 +1029,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
Error(_("codec/audio: decoded data smaller than encoded\n"));
return -1;
}
spdif[0] = htole16(0xF872); // iec 61937 sync word
spdif[0] = htole16(0xF872); // iec 61937 sync word
spdif[1] = htole16(0x4E1F);
spdif[2] = htole16(IEC61937_AC3 | (avpkt->data[5] & 0x07) << 8);
spdif[3] = htole16(avpkt->size * 8);
@@ -1068,7 +1050,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
// build SPDIF header and append A52 audio to it
// avpkt is the original data
spdif = audio_decoder->Spdif;
spdif_sz = 24576; // 4 * 6144
spdif_sz = 24576; // 4 * 6144
if (audio_decoder->HwSampleRate == 48000) {
spdif_sz = 6144;
}
@@ -1078,8 +1060,8 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
}
// check if we must pack multiple packets
repeat = 1;
if ((avpkt->data[4] & 0xc0) != 0xc0) { // fscod
static const uint8_t eac3_repeat[4] = { 6, 3, 2, 1 };
if ((avpkt->data[4] & 0xc0) != 0xc0) { // fscod
static const uint8_t eac3_repeat[4] = {6, 3, 2, 1};
// fscod2
repeat = eac3_repeat[(avpkt->data[4] & 0x30) >> 4];
@@ -1095,7 +1077,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
return 1;
}
spdif[0] = htole16(0xF872); // iec 61937 sync word
spdif[0] = htole16(0xF872); // iec 61937 sync word
spdif[1] = htole16(0x4E1F);
spdif[2] = htole16(IEC61937_EAC3);
spdif[3] = htole16(audio_decoder->SpdifIndex * 8);
@@ -1118,10 +1100,9 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder, const AVPac
** Set/update audio pts clock.
**
** @param audio_decoder audio decoder data
** @param pts presentation timestamp
** @param pts presentation timestamp
*/
static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
{
static void CodecAudioSetClock(AudioDecoder *audio_decoder, int64_t pts) {
#ifdef USE_AUDIO_DRIFT_CORRECTION
struct timespec nowtime;
int64_t delay;
@@ -1152,8 +1133,8 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
return;
}
tim_diff = (nowtime.tv_sec - audio_decoder->LastTime.tv_sec)
* 1000 * 1000 * 1000 + (nowtime.tv_nsec - audio_decoder->LastTime.tv_nsec);
tim_diff = (nowtime.tv_sec - audio_decoder->LastTime.tv_sec) * 1000 * 1000 * 1000 +
(nowtime.tv_nsec - audio_decoder->LastTime.tv_nsec);
drift = (tim_diff * 90) / (1000 * 1000) - pts_diff + delay - audio_decoder->LastDelay;
@@ -1165,7 +1146,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
if (0) {
Debug(3, "codec/audio: interval P:%5" PRId64 "ms T:%5" PRId64 "ms D:%4" PRId64 "ms %f %d\n", pts_diff / 90,
tim_diff / (1000 * 1000), delay / 90, drift / 90.0, audio_decoder->DriftCorr);
tim_diff / (1000 * 1000), delay / 90, drift / 90.0, audio_decoder->DriftCorr);
}
// underruns and av_resample have the same time :(((
if (abs(drift) > 10 * 90) {
@@ -1173,7 +1154,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
Debug(3, "codec/audio: drift(%6d) %3dms reset\n", audio_decoder->DriftCorr, drift / 90);
audio_decoder->LastDelay = 0;
#ifdef DEBUG
corr = 0; // keep gcc happy
corr = 0; // keep gcc happy
#endif
} else {
@@ -1181,14 +1162,13 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->Drift = drift;
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
&& (!(CodecPassthrough & CodecEAC3)
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
if ((CodecAudioDrift & CORRECT_AC3) &&
(!(CodecPassthrough & CodecAC3) || audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3) &&
(!(CodecPassthrough & CodecEAC3) || audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr;
}
if (audio_decoder->DriftCorr < -20000) { // limit correction
if (audio_decoder->DriftCorr < -20000) { // limit correction
audio_decoder->DriftCorr = -20000;
} else if (audio_decoder->DriftCorr > 20000) {
audio_decoder->DriftCorr = 20000;
@@ -1237,8 +1217,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
**
** @param audio_decoder audio decoder data
*/
static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
{
static void CodecAudioUpdateFormat(AudioDecoder *audio_decoder) {
int passthrough;
const AVCodecContext *audio_ctx;
@@ -1246,25 +1225,24 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
// FIXME: handle swresample format conversions.
return;
}
if (passthrough) { // pass-through no conversion allowed
if (passthrough) { // pass-through no conversion allowed
return;
}
audio_ctx = audio_decoder->AudioCtx;
#ifdef DEBUG
if (audio_ctx->sample_fmt == AV_SAMPLE_FMT_S16 && audio_ctx->sample_rate == audio_decoder->HwSampleRate
&& !CodecAudioDrift) {
if (audio_ctx->sample_fmt == AV_SAMPLE_FMT_S16 && audio_ctx->sample_rate == audio_decoder->HwSampleRate &&
!CodecAudioDrift) {
// FIXME: use Resample only, when it is needed!
fprintf(stderr, "no resample needed\n");
}
#endif
#ifdef USE_SWRESAMPLE
audio_decoder->Resample =
swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout, AV_SAMPLE_FMT_S16,
audio_decoder->HwSampleRate, audio_ctx->channel_layout, audio_ctx->sample_fmt, audio_ctx->sample_rate, 0,
NULL);
audio_decoder->Resample = swr_alloc_set_opts(audio_decoder->Resample, audio_ctx->channel_layout, AV_SAMPLE_FMT_S16,
audio_decoder->HwSampleRate, audio_ctx->channel_layout,
audio_ctx->sample_fmt, audio_ctx->sample_rate, 0, NULL);
if (audio_decoder->Resample) {
swr_init(audio_decoder->Resample);
} else {
@@ -1301,11 +1279,10 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
** @note the caller has not aligned avpkt and not cleared the end.
**
** @param audio_decoder audio decoder data
** @param avpkt audio packet
** @param avpkt audio packet
*/
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
{
void CodecAudioDecode(AudioDecoder *audio_decoder, const AVPacket *avpkt) {
AVCodecContext *audio_ctx = audio_decoder->AudioCtx;
if (audio_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
@@ -1314,7 +1291,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
AVFrame *frame = audio_decoder->Frame;
av_frame_unref(frame);
*pkt = *avpkt; // use copy
*pkt = *avpkt; // use copy
ret = avcodec_send_packet(audio_ctx, pkt);
if (ret < 0) {
Debug(3, "codec: sending audio packet failed");
@@ -1328,16 +1305,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
if (ret >= 0) {
// update audio clock
if (avpkt->pts != (int64_t) AV_NOPTS_VALUE) {
if (avpkt->pts != (int64_t)AV_NOPTS_VALUE) {
CodecAudioSetClock(audio_decoder, avpkt->pts);
}
// format change
if (audio_decoder->Passthrough != CodecPassthrough || audio_decoder->SampleRate != audio_ctx->sample_rate
|| audio_decoder->Channels != audio_ctx->channels) {
if (audio_decoder->Passthrough != CodecPassthrough ||
audio_decoder->SampleRate != audio_ctx->sample_rate ||
audio_decoder->Channels != audio_ctx->channels) {
CodecAudioUpdateFormat(audio_decoder);
}
if (!audio_decoder->HwSampleRate || !audio_decoder->HwChannels) {
return; // unsupported sample format
return; // unsupported sample format
}
if (CodecAudioPassthroughHelper(audio_decoder, avpkt)) {
return;
@@ -1347,13 +1325,12 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
uint8_t *out[1];
out[0] = outbuf;
ret =
swr_convert(audio_decoder->Resample, out, sizeof(outbuf) / (2 * audio_decoder->HwChannels),
(const uint8_t **)frame->extended_data, frame->nb_samples);
ret = swr_convert(audio_decoder->Resample, out, sizeof(outbuf) / (2 * audio_decoder->HwChannels),
(const uint8_t **)frame->extended_data, frame->nb_samples);
if (ret > 0) {
if (!(audio_decoder->Passthrough & CodecPCM)) {
CodecReorderAudioFrame((int16_t *) outbuf, ret * 2 * audio_decoder->HwChannels,
audio_decoder->HwChannels);
CodecReorderAudioFrame((int16_t *)outbuf, ret * 2 * audio_decoder->HwChannels,
audio_decoder->HwChannels);
}
AudioEnqueue(outbuf, ret * 2 * audio_decoder->HwChannels);
}
@@ -1370,11 +1347,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
**
** @param decoder audio decoder data
*/
void CodecAudioFlushBuffers(AudioDecoder * decoder)
{
avcodec_flush_buffers(decoder->AudioCtx);
}
void CodecAudioFlushBuffers(AudioDecoder *decoder) { avcodec_flush_buffers(decoder->AudioCtx); }
//----------------------------------------------------------------------------
// Codec
@@ -1383,18 +1356,13 @@ void CodecAudioFlushBuffers(AudioDecoder * decoder)
/**
** Empty log callback
*/
static void CodecNoopCallback( __attribute__((unused))
void *ptr, __attribute__((unused))
int level, __attribute__((unused))
const char *fmt, __attribute__((unused)) va_list vl)
{
}
static void CodecNoopCallback(__attribute__((unused)) void *ptr, __attribute__((unused)) int level,
__attribute__((unused)) const char *fmt, __attribute__((unused)) va_list vl) {}
/**
** Codec init
*/
void CodecInit(void)
{
void CodecInit(void) {
pthread_mutex_init(&CodecLockMutex, NULL);
#ifndef DEBUG
// disable display ffmpeg error messages
@@ -1407,7 +1375,4 @@ void CodecInit(void)
/**
** Codec exit.
*/
void CodecExit(void)
{
pthread_mutex_destroy(&CodecLockMutex);
}
void CodecExit(void) { pthread_mutex_destroy(&CodecLockMutex); }