avcpp  2.0
Wrapper for the FFmpeg that simplify usage from C++ projects.
formatcontext.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <chrono>
5 #include <functional>
6 #include <vector>
7 
8 #include "ffmpeg.h"
9 #include "format.h"
10 #include "avutils.h"
11 #include "stream.h"
12 #include "packet.h"
13 #include "codec.h"
14 #include "dictionary.h"
15 #include "averror.h"
16 
17 #if AVCPP_HAS_AVFORMAT
18 
19 extern "C" {
20 #include <libavformat/avformat.h>
21 }
22 
23 namespace av {
24 
25 using AvioInterruptCb = std::function<int()>;
26 
42 struct CustomIO
43 {
44  virtual ~CustomIO() {}
45 
60  virtual int write(const uint8_t *data, size_t size)
61  {
62  static_cast<void>(data);
63  static_cast<void>(size);
64  return -1;
65  }
66 
82  virtual int read(uint8_t *data, size_t size)
83  {
84  static_cast<void>(data);
85  static_cast<void>(size);
86  return -1;
87  }
88 
103  virtual int64_t seek(int64_t offset, int whence)
104  {
105  static_cast<void>(offset);
106  static_cast<void>(whence);
107  return -1;
108  }
109 
117  virtual int seekable() const { return 0; }
118 
124  virtual const char* name() const { return ""; }
125 };
126 
127 class FormatContext : public FFWrapperPtr<AVFormatContext>, public noncopyable
128 {
129 #if AVCPP_CXX_STANDARD >= 20
130  struct _StreamTransform {
131  const FormatContext *_parent{};
132  Stream operator()(AVStream *st) const {
133  assert(_parent);
134  return Stream{_parent->m_monitor, st, _parent->isOutput() ? Direction::Encoding : Direction::Decoding};
135  }
136  };
137  using StreamsView = std::ranges::transform_view<std::span<AVStream*>, _StreamTransform>;
138 #endif
139 
140 public:
141  FormatContext();
142  ~FormatContext();
143 
144  void setSocketTimeout(int64_t timeout);
145  void setInterruptCallback(const AvioInterruptCb& cb);
146 
147  void setFormat(const InputFormat& format);
148  void setFormat(const OutputFormat& format);
149 
150  InputFormat inputFormat() const;
151  OutputFormat outputFormat() const;
152 
153  bool isOutput() const;
154  bool isOpened() const;
155 
156  void flush();
157  void close();
158  void dump() const;
159 
160  //
161  // Streams
162  //
163  size_t streamsCount() const;
164  Stream stream(size_t idx);
165  Stream stream(size_t idx, OptionalErrorCode ec);
166  [[deprecated("Codec is not used by the FFmpeg API. Use addStream() without codec and point configured codec context after")]]
167  Stream addStream(const Codec &codec, OptionalErrorCode ec = throws());
168  Stream addStream(OptionalErrorCode ec = throws());
169  Stream addStream(const class VideoEncoderContext& encCtx, OptionalErrorCode ec = throws());
170  Stream addStream(const class AudioEncoderContext& encCtx, OptionalErrorCode ec = throws());
171 
172 #if AVCPP_CXX_STANDARD >= 20
173  StreamsView streams(OptionalErrorCode ec = throws()) const;
174 #endif
175 
176  //
177  // Seeking
178  //
179  bool seekable() const noexcept;
180  void seek(const Timestamp& timestamp, OptionalErrorCode ec = throws());
181  void seek(const Timestamp& timestamp, size_t streamIndex, OptionalErrorCode ec = throws());
182  void seek(const Timestamp& timestamp, bool anyFrame, OptionalErrorCode ec = throws());
183  void seek(const Timestamp& timestamp, size_t streamIndex, bool anyFrame, OptionalErrorCode ec = throws());
184 
185  void seek(int64_t position, int streamIndex, int flags, OptionalErrorCode ec = throws());
186 
187  //
188  // Other tools
189  //
190  Timestamp startTime() const noexcept;
191  Timestamp duration() const noexcept;
192  void substractStartTime(bool enable);
193 
200  int eventFlags() const noexcept;
201  bool eventFlags(int flags) const noexcept;
202  void eventFlagsClear(int flags) noexcept;
203 
204  //
205  // Input
206  //
207  void openInput(const std::string& uri, OptionalErrorCode ec = throws());
208  void openInput(const std::string& uri, Dictionary &formatOptions, OptionalErrorCode ec = throws());
209  void openInput(const std::string& uri, Dictionary &&formatOptions, OptionalErrorCode ec = throws());
210 
211  void openInput(const std::string& uri, InputFormat format, OptionalErrorCode ec = throws());
212  void openInput(const std::string& uri, Dictionary &formatOptions, InputFormat format, OptionalErrorCode ec = throws());
213  void openInput(const std::string& uri, Dictionary &&formatOptions, InputFormat format, OptionalErrorCode ec = throws());
214 
215  static constexpr size_t CUSTOM_IO_DEFAULT_BUFFER_SIZE = 200000;
216 
217  void openInput(CustomIO *io,
218  OptionalErrorCode ec = throws(),
219  size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE)
220  {
221  return openInput(io, InputFormat(), ec, internalBufferSize);
222  }
223  void openInput(CustomIO *io,
224  Dictionary &formatOptions,
225  OptionalErrorCode ec = throws(),
226  size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE)
227  {
228  return openInput(io, formatOptions, InputFormat(), ec, internalBufferSize);
229  }
230  void openInput(CustomIO *io,
231  Dictionary &&formatOptions,
232  OptionalErrorCode ec = throws(),
233  size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE)
234  {
235  return openInput(io, std::move(formatOptions), InputFormat(), ec, internalBufferSize);
236  }
237 
238  void openInput(CustomIO *io,
239  InputFormat format,
240  OptionalErrorCode ec = throws(),
241  size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
242  void openInput(CustomIO *io,
243  Dictionary &formatOptions,
244  InputFormat format,
245  OptionalErrorCode ec = throws(),
246  size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
247  void openInput(CustomIO *io,
248  Dictionary &&formatOptions,
249  InputFormat format,
250  OptionalErrorCode ec = throws(),
251  size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
252 
253  void findStreamInfo(OptionalErrorCode ec = throws());
254  void findStreamInfo(DictionaryArray &streamsOptions, OptionalErrorCode ec = throws());
255  void findStreamInfo(DictionaryArray &&streamsOptions, OptionalErrorCode ec = throws());
256 
257  Packet readPacket(OptionalErrorCode ec = throws());
258 
259  //
260  // Output
261  //
262  void openOutput(const std::string& uri, OptionalErrorCode ec = throws());
263  void openOutput(const std::string& uri, Dictionary &options, OptionalErrorCode ec = throws());
264  void openOutput(const std::string& uri, Dictionary &&options, OptionalErrorCode ec = throws());
265 
266  void openOutput(const std::string& uri, OutputFormat format, OptionalErrorCode ec = throws());
267  void openOutput(const std::string& uri, Dictionary &options, OutputFormat format, OptionalErrorCode ec = throws());
268  void openOutput(const std::string& uri, Dictionary &&options, OutputFormat format, OptionalErrorCode ec = throws());
269 
271 
282  void openOutput(CustomIO *io, OptionalErrorCode ec = throws(), size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
283  bool openOutput(CustomIO *io, Dictionary &formatOptions, OptionalErrorCode ec = throws(), size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
284  bool openOutput(CustomIO *io, Dictionary &&formatOptions, OptionalErrorCode ec = throws(), size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
285 
286  void openOutput(CustomIO *io, OutputFormat format, OptionalErrorCode ec = throws(), size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
287  bool openOutput(CustomIO *io, Dictionary &formatOptions, OutputFormat format, OptionalErrorCode ec = throws(), size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
288  bool openOutput(CustomIO *io, Dictionary &&formatOptions, OutputFormat format, OptionalErrorCode ec = throws(), size_t internalBufferSize = CUSTOM_IO_DEFAULT_BUFFER_SIZE);
290 
292 
304  bool initOutput(OptionalErrorCode ec = throws());
305  bool initOutput(Dictionary &options, OptionalErrorCode ec = throws());
306  bool initOutput(Dictionary &&options, OptionalErrorCode ec = throws());
308 
309  void writeHeader(OptionalErrorCode ec = throws());
310  void writeHeader(Dictionary &options, OptionalErrorCode ec = throws());
311  void writeHeader(Dictionary &&options, OptionalErrorCode ec = throws());
312 
313  void writePacket(OptionalErrorCode ec = throws());
314  void writePacket(const Packet &pkt, OptionalErrorCode ec = throws());
315  void writePacketDirect(OptionalErrorCode ec = throws());
316  void writePacketDirect(const Packet &pkt, OptionalErrorCode ec = throws());
317 
318  bool checkUncodedFrameWriting(size_t streamIndex, std::error_code &ec) noexcept;
319  bool checkUncodedFrameWriting(size_t streamIndex) noexcept;
320 
321  void writeUncodedFrame(class VideoFrame &frame, size_t streamIndex, OptionalErrorCode ec = throws());
322  void writeUncodedFrameDirect(class VideoFrame &frame, size_t streamIndex, OptionalErrorCode ec = throws());
323  void writeUncodedFrame(class AudioSamples &frame, size_t streamIndex, OptionalErrorCode ec = throws());
324  void writeUncodedFrameDirect(class AudioSamples &frame, size_t streamIndex, OptionalErrorCode ec = throws());
325 
326  void writeTrailer(OptionalErrorCode ec = throws());
327 
328 private:
329  void openInput(const std::string& uri, InputFormat format, AVDictionary **options, OptionalErrorCode ec);
330  void openOutput(const std::string& uri, OutputFormat format, AVDictionary **options, OptionalErrorCode ec);
331  bool initOutput(Dictionary &options, bool closeOnError, OptionalErrorCode ec);
332  bool initOutput(AVDictionary **options, OptionalErrorCode ec);
333  void writeHeader(AVDictionary **options, OptionalErrorCode ec);
334  void writePacket(const Packet &pkt, OptionalErrorCode ec, int(*write_proc)(AVFormatContext *, AVPacket *));
335  void writeFrame(AVFrame *frame, int streamIndex, OptionalErrorCode ec, int(*write_proc)(AVFormatContext*,int,AVFrame*));
336 
337  Stream addStream(const class CodecContext2 &ctx, OptionalErrorCode ec);
338 
339  static int avioInterruptCb(void *opaque);
340  int avioInterruptCb();
341  void setupInterruptHandling();
342  void resetSocketAccess();
343  void findStreamInfo(AVDictionary **options, size_t optionsCount, OptionalErrorCode ec);
344  void closeCodecContexts();
345  int checkPbError(int stat);
346 
347  void openCustomIO(CustomIO *io, size_t internalBufferSize, bool isWritable, OptionalErrorCode ec);
348  void openCustomIOInput(CustomIO *io, size_t internalBufferSize, OptionalErrorCode ec);
349  void openCustomIOOutput(CustomIO *io, size_t internalBufferSize, OptionalErrorCode ec);
350 
351 private:
352  std::shared_ptr<char> m_monitor {new char};
353  std::chrono::time_point<std::chrono::system_clock> m_lastSocketAccess;
354  int64_t m_socketTimeout = -1;
355  AvioInterruptCb m_interruptCb;
356 
357  bool m_isOpened = false;
358  bool m_customIO = false;
359  bool m_streamsInfoFound = false;
360  bool m_headerWriten = false;
361  bool m_substractStartTime = false;
362 };
363 
364 } // namespace av
365 
366 #endif // if AVCPP_HAS_AVFORMAT
Definition: audioresampler.cpp:8
OptionalErrorCode throws()
Helper to construct null OptionalErrorCode object.
Definition: averror.h:181
Definition: averror.h:230
Definition: ffmpeg.h:22