Fix bugs in previous commit that caused FTBFS in synfig and ETL FTBFS with older...
[synfig.git] / synfig-core / tags / synfig_0_61_04 / synfig-core / src / modules / mod_libavcodec / libavcodec / avcodec.c
1 /**
2  * @file avcodec.c
3  * avcodec.
4  */
5
6 #include "errno.h"
7 #include "avcodec.h"
8
9 #ifndef MKTAG
10 #define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
11 #endif
12
13 // private structure used to hide all internal memory allocations
14 // and structures used for de/encoding - end user should
15 // never see any complicated structure
16 typedef struct private_handle
17 {
18     AVCodec* avcodec;
19     AVCodecContext avcontext;
20     struct private_handle* next;
21     struct private_handle* prev;
22 } private_handle_t;
23
24 static private_handle_t* handle_first = 0;
25
26 static AVCodec* avcodec_find_by_fcc(uint32_t fcc)
27 {
28     // translation table
29     static const struct fcc_to_avcodecid {
30         enum CodecID codec;
31         uint32_t list[4]; // maybe we could map more fcc to same codec
32     } lc[] = {
33         { CODEC_ID_H263, { MKTAG('U', '2', '6', '3'), 0 } },
34         { CODEC_ID_H263I, { MKTAG('I', '2', '6', '3'), 0 } },
35         { CODEC_ID_MSMPEG4V3, { MKTAG('D', 'I', 'V', '3'), 0 } },
36         { CODEC_ID_MPEG4, { MKTAG('D', 'I', 'V', 'X'),  MKTAG('D', 'X', '5', '0'), 0 } },
37         { CODEC_ID_MSMPEG4V2, { MKTAG('M', 'P', '4', '2'), 0 } },
38         { CODEC_ID_MJPEG, { MKTAG('M', 'J', 'P', 'G'), 0 } },
39         { CODEC_ID_MPEG1VIDEO, { MKTAG('P', 'I', 'M', '1'), 0 } },
40         { CODEC_ID_AC3, { 0x2000, 0 } },
41         { CODEC_ID_MP2, { 0x50, 0x55, 0 } },
42         { CODEC_ID_FLV1, { MKTAG('F', 'L', 'V', '1'), 0 } },
43
44         { CODEC_ID_NONE, {0}}
45     };
46     const struct fcc_to_avcodecid* c;
47
48     for (c = lc; c->codec != CODEC_ID_NONE; c++)
49     {
50         int i = 0;
51         while (c->list[i] != 0)
52             if (c->list[i++] == fcc)
53                 return avcodec_find_decoder(c->codec);
54     }
55
56     return NULL;
57 }
58
59 static private_handle_t* create_handle(void)
60 {
61     private_handle_t* t = av_malloc(sizeof(private_handle_t));
62     if (!t)
63         return NULL;
64     memset(t, 0, sizeof(*t));
65
66     // register and fill
67     if (!handle_first)
68     {
69         avcodec_init();
70         avcodec_register_all();
71         handle_first = t;
72     }
73     else
74     {
75         t->prev = handle_first->next;
76         handle_first->next = t;
77         t->next = handle_first;
78     }
79
80     return t;
81 }
82
83 static void destroy_handle(private_handle_t* handle)
84 {
85     if (handle)
86     {
87         if (handle->avcodec)
88         {
89             avcodec_close(&handle->avcontext);
90         }
91         av_free(handle);
92
93         // count referencies
94     }
95 }
96
97 int avcodec(void* handle, avc_cmd_t cmd, void* pin, void* pout)
98 {
99     AVCodecContext* ctx = handle;
100     switch (cmd)
101     {
102     case AVC_OPEN_BY_NAME:
103         {
104             // pin  char* codec name
105             private_handle_t* h = create_handle();
106             (private_handle_t**)pout = h;
107             if (!h)
108                 return -ENOMEM;
109             if (!h->avcodec)
110             {
111                 destroy_handle(h);
112                 (private_handle_t**)pout = NULL;
113                 return -1;// better error
114             }
115             return 0;
116         }
117     case AVC_OPEN_BY_CODEC_ID:
118         {
119             // pin  uint32_t codec fourcc
120             private_handle_t* h = create_handle();
121             (private_handle_t**)pout = h;
122             if (!h)
123                 return -ENOMEM;
124
125             if (!h->avcodec)
126             {
127                 destroy_handle(h);
128                 (private_handle_t**)pout = NULL;
129                 return -1;// better error
130             }
131             return 0;
132         }
133     case AVC_OPEN_BY_FOURCC:
134         {
135             // pin  uint32_t codec fourcc
136             private_handle_t* h = create_handle();
137             (private_handle_t**)pout = h;
138             if (!h)
139                 return -ENOMEM;
140             h->avcodec = avcodec_find_by_fcc((uint32_t) pin);
141             if (!h->avcodec)
142             {
143                 destroy_handle(h);
144                 (private_handle_t**)pout = NULL;
145                 return -1;// better error
146             }
147             return 0;
148         }
149     case AVC_CLOSE:
150         // uninit part
151         // eventually close all allocated space if this was last
152         // instance
153         destroy_handle(handle);
154         break;
155
156     case AVC_FLUSH:
157         break;
158
159     case AVC_DECODE:
160         break;
161
162     case AVC_ENCODE:
163         break;
164
165     case AVC_GET_VERSION:
166         (int*) pout = 500;
167     default:
168         return -1;
169
170     }
171     return 0;
172 }