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