xref: /haiku/src/add-ons/media/plugins/ffmpeg/FFmpegPlugin.cpp (revision c0936b5a0384bc6fe654d296ee54222a0f45d2b6)
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 "avcodec.h"
23 	#include "avformat.h"
24 }
25 
26 #include "AVCodecDecoder.h"
27 #include "AVCodecEncoder.h"
28 #include "AVFormatReader.h"
29 #include "AVFormatWriter.h"
30 #include "CodecTable.h"
31 #include "EncoderTable.h"
32 #include "MuxerTable.h"
33 
34 
35 //#define TRACE_FFMPEG_PLUGIN
36 #ifdef TRACE_FFMPEG_PLUGIN
37 #	define TRACE printf
38 #else
39 #	define TRACE(a...)
40 #endif
41 
42 #define ERROR(a...) fprintf(stderr, a)
43 
44 
45 static int
46 manage_locks(void** _lock, enum AVLockOp operation)
47 {
48 	TRACE("manage_locks(%p, %d)\n", *_lock, operation);
49 
50 	BLocker** lock = reinterpret_cast<BLocker**>(_lock);
51 
52 	switch (operation) {
53 		case AV_LOCK_CREATE:
54 			TRACE("  AV_LOCK_CREATE\n");
55 			*lock = new(std::nothrow) BLocker("FFmpeg lock");
56 			if (*lock == NULL)
57 				return 1;
58 			break;
59 
60 		case AV_LOCK_OBTAIN:
61 			TRACE("  AV_LOCK_OBTAIN\n");
62 			if (!(*lock)->Lock())
63 				return 1;
64 			break;
65 
66 		case AV_LOCK_RELEASE:
67 			TRACE("  AV_LOCK_RELEASE\n");
68 			(*lock)->Unlock();
69 			break;
70 
71 		case AV_LOCK_DESTROY:
72 			TRACE("  AV_LOCK_DESTROY\n");
73 			delete *lock;
74 			break;
75 
76 		default:
77 			return 1;
78 	}
79 	return 0;
80 }
81 
82 
83 FFmpegPlugin::GlobalInitilizer::GlobalInitilizer()
84 {
85 	if (av_lockmgr_register(manage_locks) != 0)
86 		ERROR("Failed to register lock management!\n");
87 
88 	av_register_all();
89 		// This will also call av_codec_init() by registering codecs.
90 #if LIBAVCODEC_VERSION_INT >= ((57 << 16) | (0 << 8))
91 	avfilter_register_all();
92 #endif
93 }
94 
95 
96 FFmpegPlugin::GlobalInitilizer::~GlobalInitilizer()
97 {
98 	av_lockmgr_register(NULL);
99 }
100 
101 
102 FFmpegPlugin::GlobalInitilizer FFmpegPlugin::sInitilizer;
103 
104 
105 // #pragma mark -
106 
107 
108 Decoder*
109 FFmpegPlugin::NewDecoder(uint index)
110 {
111 // TODO: Confirm we can check index here.
112 //	if (index == 0)
113 		return new(std::nothrow) AVCodecDecoder();
114 //	return NULL;
115 }
116 
117 
118 Reader*
119 FFmpegPlugin::NewReader()
120 {
121 	return new(std::nothrow) AVFormatReader();
122 }
123 
124 
125 status_t
126 FFmpegPlugin::GetSupportedFormats(media_format** _formats, size_t* _count)
127 {
128 	return build_decoder_formats(_formats, _count);
129 }
130 
131 
132 Writer*
133 FFmpegPlugin::NewWriter()
134 {
135 	return new(std::nothrow) AVFormatWriter();
136 }
137 
138 
139 status_t
140 FFmpegPlugin::GetSupportedFileFormats(const media_file_format** _fileFormats,
141 	size_t* _count)
142 {
143 	*_fileFormats = gMuxerTable;
144 	*_count = gMuxerCount;
145 	return B_OK;
146 }
147 
148 
149 Encoder*
150 FFmpegPlugin::NewEncoder(const media_codec_info& codecInfo)
151 {
152 	for (size_t i = 0; i < gEncoderCount; i++) {
153 		if (codecInfo.sub_id == gEncoderTable[i].codec_info.sub_id) {
154 			return new(std::nothrow)AVCodecEncoder(codecInfo.sub_id,
155 				gEncoderTable[i].bit_rate_scale);
156 		}
157 	}
158 	return NULL;
159 }
160 
161 
162 Encoder*
163 FFmpegPlugin::NewEncoder(const media_format& format)
164 {
165 	for (size_t i = 0; i < gEncoderCount; i++) {
166 		if (format.type == gEncoderTable[i].output_type) {
167 			return new(std::nothrow)AVCodecEncoder(
168 				gEncoderTable[i].codec_info.sub_id,
169 				gEncoderTable[i].bit_rate_scale);
170 		}
171 	}
172 	return NULL;
173 }
174 
175 
176 status_t
177 FFmpegPlugin::RegisterNextEncoder(int32* cookie, media_codec_info* _codecInfo,
178 	media_format_family* _formatFamily, media_format* _inputFormat,
179 	media_format* _outputFormat)
180 {
181 	if (*cookie < 0 || *cookie >= (int32)gEncoderCount)
182 		return B_BAD_INDEX;
183 
184 	*_codecInfo = gEncoderTable[*cookie].codec_info;
185 	*_formatFamily = gEncoderTable[*cookie].format_family;
186 	_inputFormat->type = gEncoderTable[*cookie].input_type;
187 	_outputFormat->type = gEncoderTable[*cookie].output_type;;
188 
189 	*cookie = *cookie + 1;
190 
191 	return B_OK;
192 }
193 
194 
195 // #pragma mark -
196 
197 
198 MediaPlugin*
199 instantiate_plugin()
200 {
201 	return new(std::nothrow) FFmpegPlugin;
202 }
203 
204