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