AVPKit
Codec.cpp
1 /*******************************************************************************
2  * Copyright (c) 2024, 2026, Olivier Ayache. All rights reserved.
3  *
4  * This file is part of AVPKit.
5  *
6  * AVPKit is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * AVPKit is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with AVPKit. If not, see <http://www.gnu.org/licenses/>.
18  *******************************************************************************/
19 
20 #include <com/avpkit/ferry/Logger.h>
21 #include <com/avpkit/ferry/RefPointer.h>
22 #include <com/avpkit/core/Global.h>
23 #include <com/avpkit/core/Codec.h>
24 #include <com/avpkit/core/ContainerFormat.h>
25 
26 VS_LOG_SETUP(VS_CPP_PACKAGE);
27 
28 namespace com { namespace avpkit { namespace core
29 {
30  using namespace com::avpkit::ferry;
31 
32  Codec :: Codec()
33  {
34  VS_LOG_TRACE("Starting");
35  mCodec = 0;
36  }
37 
38  Codec :: ~Codec()
39  {
40  // no memory freeing required.
41  mCodec = 0;
42  }
43 
44  const char *
46  const char * retval = 0;
47  if (mCodec)
48  retval = mCodec->name;
49  return retval;
50  }
51 
52  int
54  {
55  int retval = AV_CODEC_ID_NONE;
56  if (mCodec)
57  retval = mCodec->id;
58  return retval;
59  }
60 
63  {
64  Type retval = (Type) AVMEDIA_TYPE_UNKNOWN;
65  if (mCodec)
66  retval = (Type) mCodec->type;
67  return retval;
68  }
69 
70  Codec *
71  Codec :: make(const AVCodec *aCodec)
72  {
73  Codec *retval = 0;
74  if (aCodec)
75  {
76  retval = Codec::make();
77  if (retval)
78  retval->mCodec = aCodec;
79  }
80  return retval;
81  }
82 
83  Codec *
84  Codec :: findEncodingCodec(const ICodec::ID id, const IPixelFormat::Type type)
85  {
86  if (IPixelFormat::NONE == type){
87  return Codec::findEncodingCodecByIntID((const int)id);
88  }
89 
90  AVHWAccel *hwaccel = NULL;
91 
92  while ((hwaccel = av_hwaccel_next(hwaccel))){
93  if (hwaccel->id == id && hwaccel->pix_fmt == type){
94  return findEncodingCodecByName(hwaccel->name);
95  }
96  }
97 
98  return NULL;
99 
100  }
101  Codec *
102  Codec :: findEncodingCodecByIntID(const int id)
103  {
104  Codec *retval = 0;
105  AVCodec *codec = 0;
106  enum AVCodecID ffmpeg_id = (enum AVCodecID) id;
107  Global::lock();
108  codec = avcodec_find_encoder(ffmpeg_id);
109  Global::unlock();
110  if (codec)
111  retval = Codec::make(codec);
112 
113  return retval;
114  }
115 
116  Codec *
117  Codec :: findEncodingCodecByName(const char* name)
118  {
119  Codec *retval = 0;
120  AVCodec *codec = 0;
121  if (name && *name)
122  {
123  Global::lock();
124  codec = avcodec_find_encoder_by_name(name);
125  Global::unlock();
126  if (codec)
127  retval = Codec::make(codec);
128  }
129  return retval;
130  }
131 
132  Codec *
133  Codec :: findDecodingCodec(const ICodec::ID id, const IPixelFormat::Type type)
134  {
135 
136  if (IPixelFormat::NONE == type){
137  return Codec::findDecodingCodecByIntID((const int)id);
138  }
139 
140  AVHWAccel *hwaccel = NULL;
141 
142  while ((hwaccel = av_hwaccel_next(hwaccel))){
143  if (hwaccel->id == id && hwaccel->pix_fmt == type){
144  return findDecodingCodecByName(hwaccel->name);
145  }
146  }
147 
148  return NULL;
149  }
150 
151  Codec *
152  Codec :: findDecodingCodecByIntID(const int id)
153  {
154  Codec *retval = 0;
155  AVCodec *codec = 0;
156 
157  Global::lock();
158  codec = avcodec_find_decoder((enum AVCodecID) id);
159  Global::unlock();
160 
161  if (codec)
162  retval = Codec::make(codec);
163  return retval;
164  }
165 
166  Codec *
167  Codec :: findDecodingCodecByName(const char* name)
168  {
169  Codec *retval = 0;
170  AVCodec *codec = 0;
171  if (name && *name)
172  {
173  Global::lock();
174  codec = avcodec_find_decoder_by_name(name);
175  Global::unlock();
176  if (codec)
177  retval = Codec::make(codec);
178  }
179  return retval;
180  }
181  bool
183  {
184  return mCodec ? (mCodec->decode != NULL) : false;
185  }
186 
187  bool
189  {
190  return mCodec ? (mCodec->encode2 != NULL) : false;
191  }
192 
193  Codec*
194  Codec :: guessEncodingCodec(IContainerFormat* pFmt,
195  const char* shortName,
196  const char* url,
197  const char* mimeType,
198  ICodec::Type type)
199  {
200  Codec* retval = 0;
202  AVOutputFormat * oFmt = 0;
203 
204  // We acquire here because the RefPointer always
205  // releases.
206  fmt.reset(dynamic_cast<ContainerFormat*>(pFmt), true);
207 
208  if (!fmt)
209  {
210  fmt = ContainerFormat::make();
211  if (fmt)
212  fmt->setOutputFormat(shortName, url, mimeType);
213  }
214  if (fmt)
215  oFmt = fmt->getOutputFormat();
216 
217  // Make sure at least one in put is specified.
218  // The av_guess_codec function REQUIRES a
219  // non null AVOutputFormat
220  // It also examines url with a strcmp(), so let's
221  // give it a zero-length string.
222  // In reality, it ignores the other params.
223  if (!url)
224  url = "";
225 
226  if (oFmt)
227  {
228  enum AVCodecID id = av_guess_codec(oFmt, shortName, url,
229  mimeType, (enum AVMediaType) type);
230  retval = Codec::findEncodingCodecByIntID((int)id);
231  }
232  return retval;
233  }
234 
235  int32_t
237  {
238  int retval = 0;
239  retval = RefCounted::acquire();
240  VS_LOG_TRACE("Acquired %p: %d", this, retval);
241  return retval;
242  }
243  int32_t
245  {
246  int retval = 0;
247  retval = RefCounted::release();
248  VS_LOG_TRACE("Released %p: %d", this, retval);
249  return retval;
250  }
251  const char *
253  {
254  return mCodec ? mCodec->long_name : 0;
255  }
256 
257  int32_t
259  {
260  if (!mCodec)
261  return 0;
262  return mCodec->capabilities;
263  }
264  bool
266  {
267  if (!mCodec)
268  return false;
269  return mCodec->capabilities&flag;
270  }
271 
272  int32_t
274  {
275  if (!mCodec)
276  return 0;
277  int count = 0;
278  for(
279  const AVRational* p=mCodec->supported_framerates;
280  p && !(!p->den && !p->num);
281  p++
282  )
283  ++count;
284  return count;
285  }
286  IRational*
288  {
289  if (!mCodec)
290  return 0;
291  int i = 0;
292  for(
293  const AVRational* p=mCodec->supported_framerates;
294  p && !(!p->den && !p->num);
295  p++, i++
296  )
297  if (index == i)
298  return IRational::make(p->num,p->den);
299  return 0;
300  }
301 
302  int32_t
304  {
305  if (!mCodec)
306  return 0;
307  int count = 0;
308  for(const AVPixelFormat* p = mCodec->pix_fmts;
309  p && (*p!=-1);
310  p++)
311  ++count;
312  return count;
313 
314  }
315 
318  {
319  if (!mCodec)
320  return IPixelFormat::NONE;
321  int i = 0;
322  for(const AVPixelFormat* p = mCodec->pix_fmts;
323  p && (*p!=-1);
324  p++,i++)
325  if (index == i)
326  return (IPixelFormat::Type)*p;
327  return IPixelFormat::NONE;
328  }
329 
330  int32_t
332  {
333  if (!mCodec)
334  return 0;
335  int i = 0;
336  for(const int *p = mCodec->supported_samplerates;
337  p && *p;
338  ++p, ++i)
339  ;
340  return i;
341  }
342  int32_t
344  {
345  if (!mCodec)
346  return 0;
347  int i = 0;
348  for(const int *p = mCodec->supported_samplerates;
349  p && *p;
350  p++, i++)
351  if (i == index)
352  return *p;
353  return 0;
354  }
355 
356  int32_t
358  {
359  if (!mCodec)
360  return 0;
361  int i = 0;
362  for(const enum AVSampleFormat* p=mCodec->sample_fmts;
363  p && (*p != -1);
364  p++,i++)
365  ;
366  return i;
367  }
368 
371  {
372  if (!mCodec)
373  return IAudioSamples::FMT_NONE;
374  int i = 0;
375  for(const enum AVSampleFormat* p=mCodec->sample_fmts;
376  p && (*p != -1);
377  p++,i++)
378  if (index == i)
379  return (IAudioSamples::Format)*p;
380  return IAudioSamples::FMT_NONE;
381 
382  }
383 
384  int32_t
386  {
387  if (!mCodec)
388  return 0;
389  int i = 0;
390  for(const uint64_t* p=mCodec->channel_layouts;
391  p && *p;
392  p++,i++)
393  ;
394  return i;
395  }
396  int64_t
398  {
399  if (!mCodec)
400  return 0;
401  int i = 0;
402  for(const uint64_t* p=mCodec->channel_layouts;
403  p && *p;
404  p++,i++)
405  if (index == i)
406  return (int64_t)*p;
407  return 0;
408  }
409 
410 }}}
virtual bool hasCapability(Capabilities flag)
Convenience method to check individual capability flags.
Definition: Codec.cpp:265
virtual bool canEncode()
Can this codec be used for encoding?
Definition: Codec.cpp:188
virtual int32_t getNumSupportedAudioChannelLayouts()
Get the number of different audio channel layouts this codec supports for encoding.
Definition: Codec.cpp:385
virtual int32_t getNumSupportedVideoPixelFormats()
Get the number of supported video pixel formats this codec supports for encoding.
Definition: Codec.cpp:303
virtual IPixelFormat::Type getSupportedVideoPixelFormat(int32_t index)
Return the supported video pixel format at the given index.
Definition: Codec.cpp:317
virtual int32_t release()
Internal Only.
Definition: Codec.cpp:244
virtual IRational * getSupportedVideoFrameRate(int32_t index)
Return the supported frame rate at the given index.
Definition: Codec.cpp:287
virtual int64_t getSupportedAudioChannelLayout(int32_t index)
Get the supported audio channel layout at this index.
Definition: Codec.cpp:397
virtual int32_t getNumSupportedAudioSampleFormats()
Get the number of different audio sample formats this codec supports for encoding.
Definition: Codec.cpp:357
virtual int32_t acquire()
Internal Only.
Definition: Codec.cpp:236
virtual IAudioSamples::Format getSupportedAudioSampleFormat(int32_t index)
Get the supported sample format at this index.
Definition: Codec.cpp:370
virtual int32_t getCapabilities()
Get the capabilites flag from the codec.
Definition: Codec.cpp:258
virtual const char * getLongName()
Added for 1.17.
Definition: Codec.cpp:252
virtual int32_t getNumSupportedVideoFrameRates()
Get the number of frame rates this codec supports for encoding.
Definition: Codec.cpp:273
virtual const char * getName()
Get the name of the codec.
Definition: Codec.cpp:45
virtual int32_t getNumSupportedAudioSampleRates()
Get the number of different audio sample rates this codec supports for encoding.
Definition: Codec.cpp:331
virtual int32_t getSupportedAudioSampleRate(int32_t index)
Return the support audio sample rate at the given index.
Definition: Codec.cpp:343
virtual bool canDecode()
Can this codec be used for decoding?
Definition: Codec.cpp:182
virtual Type getType()
Get the type of this codec.
Definition: Codec.cpp:62
virtual int getIDAsInt()
Get the ID of this codec, as an integer.
Definition: Codec.cpp:53
static void unlock()
Unlock the global lock.
Definition: Global.cpp:215
static void lock()
Performs a global-level lock of the AVPKIT library.
Definition: Global.cpp:207
Format
The format we use to represent audio.
Definition: IAudioSamples.h:46
Capabilities
Capability flags.
Definition: ICodec.h:729
ID
These are the codecs this library currently supports.
Definition: ICodec.h:61
Type
The different types of Codecs that can exist in the system.
Definition: ICodec.h:582
Specifies format information than can be used to configure an IContainer for input or output.
static IContainerFormat * make()
Create a new IContainerFormat object.
This class wraps represents a Rational number for the AVPKit.
Definition: IRational.h:43
static IRational * make()
Get a new rational that will be set to 0/0.
Definition: IRational.cpp:79
virtual int32_t acquire()
Internal Only.
Definition: RefCounted.cpp:63
virtual int32_t release()
Internal Only.
Definition: RefCounted.cpp:70
This class is only useful from C++.
Definition: RefPointer.h:47
void reset(T *ptr=0, bool acquire=false)
Reset the managed pointer, calling RefCounted::release() on the previously managed pointer first.
Definition: RefPointer.h:237
This library contains routines used by AVPKit libraries for "ferry"ing Java objects to and from nativ...
WARNING: Do not use logging in this class, and do not set any static file variables to values other t...