xref: /haiku/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
1 /*
2  * Copyright (C) 2001 Carlos Hasan
3  * Copyright (C) 2001 François Revol
4  * Copyright (C) 2001 Axel Dörfler
5  * Copyright (C) 2004 Marcus Overhagen
6  * Copyright (C) 2009 Stephan Aßmus <superstippi@gmx.de>
7  *
8  * All rights reserved. Distributed under the terms of the MIT License.
9  */
10 
11 //! libavcodec/libavformat based Decoder and Reader plugin for Haiku
12 
13 #include "FFmpegPlugin.h"
14 
15 #include <stdio.h>
16 
17 #include <new>
18 
19 #include <Locker.h>
20 
21 extern "C" {
22 	#include "avformat.h"
23 }
24 
25 #include "AVCodecDecoder.h"
26 #include "AVCodecEncoder.h"
27 #include "AVFormatReader.h"
28 #include "AVFormatWriter.h"
29 #include "CodecTable.h"
30 #include "EncoderTable.h"
31 #include "MuxerTable.h"
32 
33 
34 //#define TRACE_FFMPEG_PLUGIN
35 #ifdef TRACE_FFMPEG_PLUGIN
36 #	define TRACE printf
37 #else
38 #	define TRACE(a...)
39 #endif
40 
41 #define ERROR(a...) fprintf(stderr, a)
42 
43 
44 static int
45 manage_locks(void** _lock, enum AVLockOp operation)
46 {
47 	TRACE("manage_locks(%p, %d)\n", *_lock, operation);
48 
49 	BLocker** lock = reinterpret_cast<BLocker**>(_lock);
50 
51 	switch (operation) {
52 		case AV_LOCK_CREATE:
53 			TRACE("  AV_LOCK_CREATE\n");
54 			*lock = new(std::nothrow) BLocker("FFmpeg lock");
55 		 	if (*lock == NULL)
56 				return 1;
57 			break;
58 
59 		case AV_LOCK_OBTAIN:
60 			TRACE("  AV_LOCK_OBTAIN\n");
61 			if (!(*lock)->Lock())
62 				return 1;
63 			break;
64 
65 		case AV_LOCK_RELEASE:
66 			TRACE("  AV_LOCK_RELEASE\n");
67 			(*lock)->Unlock();
68 			break;
69 
70 		case AV_LOCK_DESTROY:
71 			TRACE("  AV_LOCK_DESTROY\n");
72 			delete *lock;
73 			break;
74 
75 		default:
76 			return 1;
77 	}
78 	return 0;
79 }
80 
81 
82 FFmpegPlugin::GlobalInitilizer::GlobalInitilizer()
83 {
84 	if (av_lockmgr_register(manage_locks) != 0)
85 		ERROR("Failed to register lock management!\n");
86 
87 	av_register_all();
88 		// This will also call av_codec_init() by registering codecs.
89 }
90 
91 
92 FFmpegPlugin::GlobalInitilizer::~GlobalInitilizer()
93 {
94 	av_lockmgr_register(NULL);
95 }
96 
97 
98 FFmpegPlugin::GlobalInitilizer FFmpegPlugin::sInitilizer;
99 
100 
101 // #pragma mark -
102 
103 
104 Decoder*
105 FFmpegPlugin::NewDecoder(uint index)
106 {
107 // TODO: Confirm we can check index here.
108 //	if (index == 0)
109 		return new(std::nothrow) AVCodecDecoder();
110 //	return NULL;
111 }
112 
113 
114 Reader*
115 FFmpegPlugin::NewReader()
116 {
117 	return new(std::nothrow) AVFormatReader();
118 }
119 
120 
121 status_t
122 FFmpegPlugin::GetSupportedFormats(media_format** _formats, size_t* _count)
123 {
124 	BMediaFormats mediaFormats;
125 	if (mediaFormats.InitCheck() != B_OK)
126 		return B_ERROR;
127 
128 	for (int i = 0; i < gCodecCount; i++) {
129 		media_format_description description;
130 		description.family = gCodecTable[i].family;
131 		switch(description.family) {
132 			case B_WAV_FORMAT_FAMILY:
133 				description.u.wav.codec = gCodecTable[i].fourcc;
134 				break;
135 			case B_AIFF_FORMAT_FAMILY:
136 				description.u.aiff.codec = gCodecTable[i].fourcc;
137 				break;
138 			case B_AVI_FORMAT_FAMILY:
139 				description.u.avi.codec = gCodecTable[i].fourcc;
140 				break;
141 			case B_MPEG_FORMAT_FAMILY:
142 				description.u.mpeg.id = gCodecTable[i].fourcc;
143 				break;
144 			case B_QUICKTIME_FORMAT_FAMILY:
145 				description.u.quicktime.codec = gCodecTable[i].fourcc;
146 				break;
147 			case B_MISC_FORMAT_FAMILY:
148 				description.u.misc.file_format =
149 					(uint32)(gCodecTable[i].fourcc >> 32);
150 				description.u.misc.codec = (uint32) gCodecTable[i].fourcc;
151 				break;
152 			default:
153 				break;
154 		}
155 		media_format format;
156 		format.type = gCodecTable[i].type;
157 		format.require_flags = 0;
158 		format.deny_flags = B_MEDIA_MAUI_UNDEFINED_FLAGS;
159 		if (mediaFormats.MakeFormatFor(&description, 1, &format) != B_OK)
160 			return B_ERROR;
161 		gAVCodecFormats[i] = format;
162 	}
163 
164 	*_formats = gAVCodecFormats;
165 	*_count = gCodecCount;
166 	return B_OK;
167 }
168 
169 
170 Writer*
171 FFmpegPlugin::NewWriter()
172 {
173 	return new(std::nothrow) AVFormatWriter();
174 }
175 
176 
177 status_t
178 FFmpegPlugin::GetSupportedFileFormats(const media_file_format** _fileFormats,
179 	size_t* _count)
180 {
181 	*_fileFormats = gMuxerTable;
182 	*_count = gMuxerCount;
183 	return B_OK;
184 }
185 
186 
187 Encoder*
188 FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo)
189 {
190 	for (size_t i = 0; i < gEncoderCount; i++) {
191 		if (codecInfo.sub_id == gEncoderTable[i].codec_info.sub_id) {
192 			return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id,
193 				gEncoderTable[i].bit_rate_scale);
194 		}
195 	}
196 	return NULL;
197 }
198 
199 
200 status_t
201 FFmpegPlugin::RegisterNextEncoder(int32* cookie, media_codec_info* _codecInfo,
202 	media_format_family* _formatFamily, media_format* _inputFormat,
203 	media_format* _outputFormat)
204 {
205 	if (*cookie < 0 || *cookie >= (int32)gEncoderCount)
206 		return B_BAD_INDEX;
207 
208 	*_codecInfo = gEncoderTable[*cookie].codec_info;
209 	*_formatFamily = gEncoderTable[*cookie].format_family;
210 	_inputFormat->type = gEncoderTable[*cookie].input_type;
211 	_outputFormat->type = gEncoderTable[*cookie].output_type;;
212 
213 	*cookie = *cookie + 1;
214 
215 	return B_OK;
216 }
217 
218 
219 // #pragma mark -
220 
221 
222 MediaPlugin*
223 instantiate_plugin()
224 {
225 	return new(std::nothrow) FFmpegPlugin;
226 }
227 
228