xref: /haiku/src/add-ons/media/plugins/ffmpeg/CodecTable.cpp (revision 95c9effd68127df2dce202d5e254a7c86560010a)
1 /*
2  * Copyright 2010 Stephan Aßmus <superstippi@gmx.de>. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "CodecTable.h"
8 
9 extern "C" {
10 	#include "avcodec.h"
11 	#include "avformat.h"
12 }
13 
14 
15 #if LIBAVCODEC_VERSION_INT > ((54 << 16) | (50 << 8))
16 typedef AVCodecID CodecID;
17 #else
18 #define AV_CODEC_ID_NONE CODEC_ID_NONE
19 #define AV_CODEC_ID_PCM_S16LE CODEC_ID_PCM_S16LE
20 #define AV_CODEC_ID_RAWVIDEO CODEC_ID_RAWVIDEO
21 #define AV_CODEC_ID_DVD_SUBTITLE CODEC_ID_DVD_SUBTITLE
22 #define AV_CODEC_ID_ADPCM_IMA_QT CODEC_ID_ADPCM_IMA_QT
23 #endif
24 
25 
26 //XXX: newer versions have it in libavformat/internal.h
27 typedef struct AVCodecTag {
28     CodecID id;
29     unsigned int tag;
30 } AVCodecTag;
31 
32 
33 struct AVInputFamily gAVInputFamilies[] = {
34 	{ B_AIFF_FORMAT_FAMILY, "aiff" },
35 	{ B_AVI_FORMAT_FAMILY, "avi" },
36 	{ B_MPEG_FORMAT_FAMILY, "mpeg" },
37 	{ B_QUICKTIME_FORMAT_FAMILY, "mov" },
38 	{ B_ANY_FORMAT_FAMILY, NULL}
39 };
40 
41 static const int32 sMaxFormatCount = 1024;
42 media_format gAVCodecFormats[sMaxFormatCount];
43 
44 
45 status_t
46 register_avcodec_tags(media_format_family family, const char *avname, int &index)
47 {
48 	AVInputFormat *inputFormat = av_find_input_format(avname);
49 	if (inputFormat == NULL)
50 		return B_MEDIA_NO_HANDLER;
51 
52 	BMediaFormats mediaFormats;
53 	if (mediaFormats.InitCheck() != B_OK)
54 		return B_ERROR;
55 
56 	for (int tagSet = 0; inputFormat->codec_tag[tagSet]; tagSet++) {
57 		const AVCodecTag *tags = inputFormat->codec_tag[tagSet];
58 		if (tags == NULL)
59 			continue;
60 
61 		for (; tags->id != AV_CODEC_ID_NONE; tags++) {
62 			// XXX: we might want to keep some strange PCM codecs too...
63 			// skip unwanted codec tags
64 			if (tags->tag == AV_CODEC_ID_RAWVIDEO
65 				|| (tags->tag >= AV_CODEC_ID_PCM_S16LE
66 					&& tags->tag < AV_CODEC_ID_ADPCM_IMA_QT)
67 				|| tags->tag >= AV_CODEC_ID_DVD_SUBTITLE)
68 				continue;
69 
70 			if (index >= sMaxFormatCount) {
71 				fprintf(stderr, "Maximum format count reached for auto-generated "
72 					"AVCodec to media_format mapping, but there are still more "
73 					"AVCodecs compiled into libavcodec!\n");
74 				break;
75 			}
76 
77 			media_format format;
78 			// Determine media type
79 			if (tags->tag < AV_CODEC_ID_PCM_S16LE)
80 				format.type = B_MEDIA_ENCODED_VIDEO;
81 			else
82 				format.type = B_MEDIA_ENCODED_AUDIO;
83 
84 			media_format_description description;
85 			memset(&description, 0, sizeof(description));
86 
87 			// Hard-code everything to B_MISC_FORMAT_FAMILY to ease matching
88 			// later on.
89 			description.family = family;
90 			switch (family) {
91 				case B_AIFF_FORMAT_FAMILY:
92 					description.u.aiff.codec = tags->tag;
93 					break;
94 				case B_AVI_FORMAT_FAMILY:
95 					description.u.avi.codec = tags->tag;
96 					break;
97 				case B_MPEG_FORMAT_FAMILY:
98 					description.u.mpeg.id = tags->tag;
99 					break;
100 				case B_QUICKTIME_FORMAT_FAMILY:
101 					description.u.quicktime.codec = tags->tag;
102 					break;
103 				case B_WAV_FORMAT_FAMILY:
104 					description.u.wav.codec = tags->tag;
105 					break;
106 				default:
107 					break;
108 			}
109 
110 			format.require_flags = 0;
111 			format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
112 
113 			if (mediaFormats.MakeFormatFor(&description, 1, &format) != B_OK)
114 				return B_ERROR;
115 
116 			gAVCodecFormats[index] = format;
117 
118 			index++;
119 		}
120 	}
121 	return B_OK;
122 }
123 
124 
125 status_t
126 build_decoder_formats(media_format** _formats, size_t* _count)
127 {
128 	BMediaFormats mediaFormats;
129 	if (mediaFormats.InitCheck() != B_OK)
130 		return B_ERROR;
131 
132 	int32 index = 0;
133 	AVCodec* codec = NULL;
134 	while ((codec = av_codec_next(codec)) != NULL) {
135 		if (index >= sMaxFormatCount) {
136 			fprintf(stderr, "Maximum format count reached for auto-generated "
137 				"AVCodec to media_format mapping, but there are still more "
138 				"AVCodecs compiled into libavcodec!\n");
139 			break;
140 		}
141 		media_format format;
142 		// Determine media type
143 		switch (codec->type) {
144 			case AVMEDIA_TYPE_VIDEO:
145 				format.type = B_MEDIA_ENCODED_VIDEO;
146 				break;
147 			case AVMEDIA_TYPE_AUDIO:
148 				format.type = B_MEDIA_ENCODED_AUDIO;
149 				break;
150 			default:
151 				// ignore this AVCodec
152 				continue;
153 		}
154 
155 		media_format_description description;
156 		memset(&description, 0, sizeof(description));
157 
158 		// Hard-code everything to B_MISC_FORMAT_FAMILY to ease matching
159 		// later on.
160 		description.family = B_MISC_FORMAT_FAMILY;
161 		description.u.misc.file_format = 'ffmp';
162 		description.u.misc.codec = codec->id;
163 
164 		format.require_flags = 0;
165 		format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
166 
167 		if (mediaFormats.MakeFormatFor(&description, 1, &format) != B_OK)
168 			return B_ERROR;
169 
170 		gAVCodecFormats[index] = format;
171 
172 		index++;
173 	}
174 
175 	*_formats = gAVCodecFormats;
176 	*_count = index;
177 
178 	return B_OK;
179 }
180 
181