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