1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
|
/**
* @file util.c Video filter using libavfilter -- utility functions
*
* Copyright (C) 2020 Mikhail Kurkov
*/
#include <stdlib.h>
#include <string.h>
#include <re.h>
#include <rem.h>
#include <baresip.h>
#include <libavutil/frame.h>
#include "util.h"
static int swap_lines(uint8_t *a, uint8_t *b, uint8_t *tmp, size_t size)
{
memcpy(tmp, a, size);
memcpy(a, b, size);
memcpy(b, tmp, size);
return 0;
}
static int reverse_lines(uint8_t *data, int linesize, int count)
{
size_t size = abs(linesize) * sizeof(uint8_t);
uint8_t *tmp = malloc(size);
if (!tmp)
return ENOMEM;
for (int i = 0; i < count/2; i++)
swap_lines(data + linesize * i,
data + linesize * (count - i - 1),
tmp,
size);
free(tmp);
return 0;
}
/*
* Sometimes AVFrame contains planes with lines in bottom-up order.
* Then linesize is negative and data points to the last row in buffer.
* Baresip uses unsigned linesizes, lets reorder lines to fix it.
*/
int avframe_ensure_topdown(AVFrame *frame)
{
int i;
if (!frame)
return EINVAL;
switch (frame->format) {
case AV_PIX_FMT_YUV420P:
for (i=0; i<4; i++) {
int ls = frame->linesize[i];
int h;
if (ls >= 0)
continue;
h = i == 0 ? frame->height : frame->height/2;
reverse_lines(frame->data[i], ls, h);
frame->data[i] = frame->data[i] + ls * (h - 1);
frame->linesize[i] = abs(ls);
}
break;
default:
/* TODO support more formats */
for (i=0; i<4; i++) {
if (frame->linesize[i] <0) {
warning("avfilter: unsupported frame"
" format with negative linesize: %d",
frame->format);
return EPROTO;
}
}
}
return 0;
}
enum AVPixelFormat vidfmt_to_avpixfmt(enum vidfmt fmt)
{
switch (fmt) {
case VID_FMT_YUV420P: return AV_PIX_FMT_YUV420P;
case VID_FMT_YUV444P: return AV_PIX_FMT_YUV444P;
case VID_FMT_NV12: return AV_PIX_FMT_NV12;
case VID_FMT_NV21: return AV_PIX_FMT_NV21;
default: return AV_PIX_FMT_NONE;
}
}
enum vidfmt avpixfmt_to_vidfmt(enum AVPixelFormat pix_fmt)
{
switch (pix_fmt) {
case AV_PIX_FMT_YUV420P: return VID_FMT_YUV420P;
case AV_PIX_FMT_YUVJ420P: return VID_FMT_YUV420P;
case AV_PIX_FMT_YUV444P: return VID_FMT_YUV444P;
case AV_PIX_FMT_NV12: return VID_FMT_NV12;
case AV_PIX_FMT_NV21: return VID_FMT_NV21;
default: return (enum vidfmt)-1;
}
}
|