File: util.c

package info (click to toggle)
baresip 1.1.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,328 kB
  • sloc: ansic: 53,606; cpp: 2,268; makefile: 332; objc: 320; python: 259; sh: 40; xml: 19
file content (113 lines) | stat: -rw-r--r-- 2,358 bytes parent folder | download
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;
	}
}