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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#include "errno.h"
#include "avcodec.h"
#ifndef MKTAG
#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
#endif
// private structure used to hide all internal memory allocations
// and structures used for de/encoding - end user should
// never see any complicated structure
typedef struct private_handle
{
AVCodec* avcodec;
AVCodecContext avcontext;
struct private_handle* next;
struct private_handle* prev;
} private_handle_t;
static private_handle_t* handle_first = 0;
static AVCodec* avcodec_find_by_fcc(uint32_t fcc)
{
// translation table
static const struct fcc_to_avcodecid {
enum CodecID codec;
uint32_t list[4]; // maybe we could map more fcc to same codec
} lc[] = {
{ CODEC_ID_H263, { MKTAG('U', '2', '6', '3'), 0 } },
{ CODEC_ID_H263I, { MKTAG('I', '2', '6', '3'), 0 } },
{ CODEC_ID_MSMPEG4V3, { MKTAG('D', 'I', 'V', '3'), 0 } },
{ CODEC_ID_MPEG4, { MKTAG('D', 'I', 'V', 'X'), MKTAG('D', 'X', '5', '0'), 0 } },
{ CODEC_ID_MSMPEG4V2, { MKTAG('M', 'P', '4', '2'), 0 } },
{ CODEC_ID_MJPEG, { MKTAG('M', 'J', 'P', 'G'), 0 } },
{ CODEC_ID_MPEG1VIDEO, { MKTAG('P', 'I', 'M', '1'), 0 } },
{ CODEC_ID_AC3, { 0x2000, 0 } },
{ CODEC_ID_MP2, { 0x50, 0x55, 0 } },
{ CODEC_ID_NONE, {0}}
};
const struct fcc_to_avcodecid* c;
for (c = lc; c->codec != CODEC_ID_NONE; c++)
{
int i = 0;
while (c->list[i] != 0)
if (c->list[i++] == fcc)
return avcodec_find_decoder(c->codec);
}
return NULL;
}
static private_handle_t* create_handle(void)
{
private_handle_t* t = av_malloc(sizeof(private_handle_t));
if (!t)
return NULL;
memset(t, 0, sizeof(*t));
// register and fill
if (!handle_first)
{
avcodec_init();
avcodec_register_all();
handle_first = t;
}
else
{
t->prev = handle_first->next;
handle_first->next = t;
t->next = handle_first;
}
return t;
}
static void destroy_handle(private_handle_t* handle)
{
if (handle)
{
if (handle->avcodec)
{
avcodec_close(&handle->avcontext);
}
av_free(handle);
// count referencies
}
}
int avcodec(void* handle, avc_cmd_t cmd, void* pin, void* pout)
{
AVCodecContext* ctx = handle;
switch (cmd)
{
case AVC_OPEN_BY_NAME:
{
// pin char* codec name
private_handle_t* h = create_handle();
(private_handle_t**)pout = h;
if (!h)
return -ENOMEM;
if (!h->avcodec)
{
destroy_handle(h);
(private_handle_t**)pout = NULL;
return -1;// better error
}
return 0;
}
case AVC_OPEN_BY_CODEC_ID:
{
// pin uint32_t codec fourcc
private_handle_t* h = create_handle();
(private_handle_t**)pout = h;
if (!h)
return -ENOMEM;
if (!h->avcodec)
{
destroy_handle(h);
(private_handle_t**)pout = NULL;
return -1;// better error
}
return 0;
}
case AVC_OPEN_BY_FOURCC:
{
// pin uint32_t codec fourcc
private_handle_t* h = create_handle();
(private_handle_t**)pout = h;
if (!h)
return -ENOMEM;
h->avcodec = avcodec_find_by_fcc((uint32_t) pin);
if (!h->avcodec)
{
destroy_handle(h);
(private_handle_t**)pout = NULL;
return -1;// better error
}
return 0;
}
case AVC_CLOSE:
// uninit part
// eventually close all allocated space if this was last
// instance
destroy_handle(handle);
break;
case AVC_FLUSH:
break;
case AVC_DECODE:
break;
case AVC_ENCODE:
break;
case AVC_GET_VERSION:
(int*) pout = 500;
default:
return -1;
}
return 0;
}
|