headers/bsd: Add sys/queue.h.
[haiku.git] / src / kits / media / FormatManager.cpp
blob61ce23705459f1f75dd2e0c331d0e493c3bf7de6
1 /*
2 * Copyright 2004-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
5 * Authors:
6 * Axel Dörfler
7 * Marcus Overhagen
8 */
11 #include "FormatManager.h"
13 #include <new>
15 #include <stdio.h>
16 #include <string.h>
18 #include <Autolock.h>
20 #include "debug.h"
23 #define TIMEOUT 5000000LL
24 // 5 seconds timeout for sending the reply
25 // TODO: do we really want to pause the server looper for this?
26 // would be better to offload this action to a second thread
29 #if 0
30 static const char*
31 family_to_string(media_format_family family)
33 switch (family) {
34 case B_ANY_FORMAT_FAMILY:
35 return "any";
36 case B_BEOS_FORMAT_FAMILY:
37 return "BeOS";
38 case B_QUICKTIME_FORMAT_FAMILY:
39 return "Quicktime";
40 case B_AVI_FORMAT_FAMILY:
41 return "AVI";
42 case B_ASF_FORMAT_FAMILY:
43 return "ASF";
44 case B_MPEG_FORMAT_FAMILY:
45 return "MPEG";
46 case B_WAV_FORMAT_FAMILY:
47 return "WAV";
48 case B_AIFF_FORMAT_FAMILY:
49 return "AIFF";
50 case B_AVR_FORMAT_FAMILY:
51 return "AVR";
52 case B_MISC_FORMAT_FAMILY:
53 return "misc";
54 default:
55 return "unknown";
60 static const char*
61 string_for_description(const media_format_description& desc, char* string,
62 size_t length)
64 switch (desc.family) {
65 case B_ANY_FORMAT_FAMILY:
66 snprintf(string, length, "any format");
67 break;
68 case B_BEOS_FORMAT_FAMILY:
69 snprintf(string, length, "BeOS format, format id 0x%lx",
70 desc.u.beos.format);
71 break;
72 case B_QUICKTIME_FORMAT_FAMILY:
73 snprintf(string, length, "Quicktime format, vendor id 0x%lx, "
74 "codec id 0x%lx", desc.u.quicktime.vendor,
75 desc.u.quicktime.codec);
76 break;
77 case B_AVI_FORMAT_FAMILY:
78 snprintf(string, length, "AVI format, codec id 0x%lx",
79 desc.u.avi.codec);
80 break;
81 case B_ASF_FORMAT_FAMILY:
82 snprintf(string, length, "ASF format, GUID %02x %02x %02x %02x "
83 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
84 desc.u.asf.guid.data[0], desc.u.asf.guid.data[1],
85 desc.u.asf.guid.data[2], desc.u.asf.guid.data[3],
86 desc.u.asf.guid.data[4], desc.u.asf.guid.data[5],
87 desc.u.asf.guid.data[6], desc.u.asf.guid.data[7],
88 desc.u.asf.guid.data[8], desc.u.asf.guid.data[9],
89 desc.u.asf.guid.data[10], desc.u.asf.guid.data[11],
90 desc.u.asf.guid.data[12], desc.u.asf.guid.data[13],
91 desc.u.asf.guid.data[14], desc.u.asf.guid.data[15]);
92 break;
93 case B_MPEG_FORMAT_FAMILY:
94 snprintf(string, length, "MPEG format, id 0x%lx", desc.u.mpeg.id);
95 break;
96 case B_WAV_FORMAT_FAMILY:
97 snprintf(string, length, "WAV format, codec id 0x%lx",
98 desc.u.wav.codec);
99 break;
100 case B_AIFF_FORMAT_FAMILY:
101 snprintf(string, length, "AIFF format, codec id 0x%lx",
102 desc.u.aiff.codec);
103 break;
104 case B_AVR_FORMAT_FAMILY:
105 snprintf(string, length, "AVR format, id 0x%lx", desc.u.avr.id);
106 break;
107 case B_MISC_FORMAT_FAMILY:
108 snprintf(string, length, "misc format, file-format id 0x%lx, "
109 "codec id 0x%lx", desc.u.misc.file_format, desc.u.misc.codec);
110 break;
111 default:
112 snprintf(string, length, "unknown format");
113 break;
115 return string;
117 #endif
120 // #pragma mark -
123 FormatManager::FormatManager()
125 fLock("format manager"),
126 fLastUpdate(0),
127 fNextCodecID(1000)
132 pthread_once_t FormatManager::sInitOnce = PTHREAD_ONCE_INIT;
133 FormatManager* FormatManager::sInstance = NULL;
136 /* static */ void
137 FormatManager::CreateInstance()
139 sInstance = new FormatManager();
143 /* static */ FormatManager*
144 FormatManager::GetInstance()
146 pthread_once(&sInitOnce, &CreateInstance);
148 return sInstance;
154 FormatManager::~FormatManager()
159 /*! This method is called when BMediaFormats asks for any updates
160 made to our format list.
161 If there were any changes since the last time, the whole
162 list will be sent back.
164 void
165 FormatManager::GetFormats(bigtime_t lastUpdate, BMessage& reply)
167 BAutolock locker(fLock);
169 if (lastUpdate >= fLastUpdate) {
170 // There weren't any changes since last time.
171 reply.AddBool("need_update", false);
173 return;
176 // Add all meta formats to the list
177 reply.AddBool("need_update", true);
178 reply.AddInt64("timestamp", system_time());
180 int32 count = fList.CountItems();
181 for (int32 i = 0; i < count; i++) {
182 meta_format* format = fList.ItemAt(i);
183 reply.AddData("formats", MEDIA_META_FORMAT_TYPE, format,
184 sizeof(meta_format));
189 status_t
190 FormatManager::MakeFormatFor(const media_format_description* descriptions,
191 int32 descriptionCount, media_format& format, uint32 flags, void* _reserved)
193 BAutolock locker(fLock);
195 int codec = fNextCodecID;
196 switch (format.type) {
197 case B_MEDIA_RAW_AUDIO:
198 case B_MEDIA_RAW_VIDEO:
199 // no marker
200 break;
201 case B_MEDIA_ENCODED_AUDIO:
202 if (format.u.encoded_audio.encoding == 0) {
203 format.u.encoded_audio.encoding
204 = (media_encoded_audio_format::audio_encoding)
205 fNextCodecID++;
206 } else {
207 UNIMPLEMENTED();
208 // TODO: Check the encoding and the format passed in for
209 // compatibility and return B_MISMATCHED_VALUES if incompatible
210 // or perhaps something else based on flags?
212 break;
213 case B_MEDIA_ENCODED_VIDEO:
214 if (format.u.encoded_video.encoding == 0) {
215 format.u.encoded_video.encoding
216 = (media_encoded_video_format::video_encoding)
217 fNextCodecID++;
218 } else {
219 UNIMPLEMENTED();
220 // TODO: Check the encoding and the format passed in for
221 // compatibility and return B_MISMATCHED_VALUES if incompatible
222 // or perhaps something else based on flags?
224 break;
225 case B_MEDIA_MULTISTREAM:
226 if (format.u.multistream.format == 0) {
227 format.u.multistream.format = fNextCodecID++;
228 } else {
229 UNIMPLEMENTED();
230 // TODO: Check the encoding and the format passed in for
231 // compatibility and return B_MISMATCHED_VALUES if incompatible
232 // or perhaps something else based on flags?
234 break;
235 default:
236 // nothing to do
237 return B_OK;
239 fLastUpdate = system_time();
241 status_t result = B_OK;
242 // TODO: Support "flags" (B_SET_DEFAULT, B_EXCLUSIVE, B_NO_MERGE)!
243 for (int32 i = 0; i < descriptionCount; i++) {
244 meta_format* metaFormat = new(std::nothrow) meta_format(
245 descriptions[i], format, codec);
246 if (metaFormat == NULL
247 || !fList.BinaryInsert(metaFormat, meta_format::Compare)) {
248 delete metaFormat;
249 result = B_NO_MEMORY;
250 break;
254 return B_OK;
258 void
259 FormatManager::RemoveFormat(const media_format& format)
261 BAutolock locker(fLock);
263 int32 foundIndex = -1;
264 for (int32 i = fList.CountItems() - 1; i >= 0; i--) {
265 meta_format* metaFormat = fList.ItemAt(i);
266 if (metaFormat->format == format) {
267 if (foundIndex != -1) {
268 printf("FormatManager::RemoveFormat() - format already "
269 "present at previous index: %" B_PRId32 "\n", foundIndex);
271 foundIndex = i;
275 if (foundIndex >= 0)
276 delete fList.RemoveItemAt(foundIndex);
277 else
278 printf("FormatManager::RemoveFormat() - format not found!\n");
280 fLastUpdate = system_time();