avcodec.c 3.6 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1 2 3 4 5
/**
 * @file avcodec.c
 * avcodec.
 */

6 7 8 9 10 11 12 13 14 15
#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
16
typedef struct private_handle
17 18 19
{
    AVCodec* avcodec;
    AVCodecContext avcontext;
20 21
    struct private_handle* next;
    struct private_handle* prev;
22 23
} private_handle_t;

24 25
static private_handle_t* handle_first = 0;

26 27 28 29 30 31 32 33 34
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 } },
35
	{ CODEC_ID_MSMPEG4V3, { MKTAG('D', 'I', 'V', '3'), 0 } },
36 37 38 39 40 41
	{ 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 } },
42
	{ CODEC_ID_FLV1, { MKTAG('F', 'L', 'V', '1'), 0 } },
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

	{ 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;
}

59
static private_handle_t* create_handle(void)
60
{
61
    private_handle_t* t = av_malloc(sizeof(private_handle_t));
62 63
    if (!t)
	return NULL;
64
    memset(t, 0, sizeof(*t));
65 66

    // register and fill
67 68 69 70 71 72 73 74 75 76 77 78 79
    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;
    }

80 81 82 83 84 85 86 87 88 89 90
    return t;
}

static void destroy_handle(private_handle_t* handle)
{
    if (handle)
    {
	if (handle->avcodec)
	{
	    avcodec_close(&handle->avcontext);
	}
91
	av_free(handle);
92 93 94 95 96 97 98 99 100 101 102 103 104

        // 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
105 106 107
	    private_handle_t* h = create_handle();
	    (private_handle_t**)pout = h;
	    if (!h)
108
		return -ENOMEM;
109
	    if (!h->avcodec)
110
	    {
111
		destroy_handle(h);
112 113 114 115 116 117 118 119
		(private_handle_t**)pout = NULL;
		return -1;// better error
	    }
            return 0;
	}
    case AVC_OPEN_BY_CODEC_ID:
	{
            // pin  uint32_t codec fourcc
120 121 122
	    private_handle_t* h = create_handle();
	    (private_handle_t**)pout = h;
	    if (!h)
123 124
		return -ENOMEM;

125
	    if (!h->avcodec)
126
	    {
127
		destroy_handle(h);
128 129 130 131 132 133 134 135
		(private_handle_t**)pout = NULL;
		return -1;// better error
	    }
            return 0;
	}
    case AVC_OPEN_BY_FOURCC:
	{
            // pin  uint32_t codec fourcc
136 137 138
	    private_handle_t* h = create_handle();
	    (private_handle_t**)pout = h;
	    if (!h)
139
		return -ENOMEM;
140 141
	    h->avcodec = avcodec_find_by_fcc((uint32_t) pin);
	    if (!h->avcodec)
142
	    {
143
		destroy_handle(h);
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
		(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;
}