Program Listing for File decoder.hpp

↰ Return to documentation for file (include/ffmpeg_encoder_decoder/decoder.hpp)

// -*-c++-*---------------------------------------------------------------------------------------
// Copyright 2024 Bernd Pfrommer <bernd.pfrommer@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef FFMPEG_ENCODER_DECODER__DECODER_HPP_
#define FFMPEG_ENCODER_DECODER__DECODER_HPP_

#include <ffmpeg_encoder_decoder/pts_map.hpp>
#include <ffmpeg_encoder_decoder/tdiff.hpp>
#include <ffmpeg_encoder_decoder/types.hpp>
#include <functional>
#include <memory>
#include <mutex>
#include <rclcpp/rclcpp.hpp>
#include <string>
#include <thread>
#include <unordered_map>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libavutil/samplefmt.h>
#include <libswscale/swscale.h>
}

namespace ffmpeg_encoder_decoder
{
class Decoder
{
public:
  using Callback = std::function<void(
    const ImageConstPtr & img, bool isKeyFrame, const std::string & avPixFormat)>;

  Decoder();

  ~Decoder();

  bool isInitialized() const
  {
    Lock lock(mutex_);
    return (codecContext_ != NULL);
  }

  bool initialize(const std::string & codec, Callback callback, const std::string & decoder);

  void setOutputMessageEncoding(const std::string & output_encoding);

  void reset();

  bool decodePacket(
    const std::string & encoding, const uint8_t * data, size_t size, uint64_t pts,
    const std::string & frame_id, const rclcpp::Time & stamp);

  bool flush();

  void setLogger(rclcpp::Logger logger)
  {
    Lock lock(mutex_);
    logger_ = logger;
  }

  void setMeasurePerformance(bool p)
  {
    Lock lock(mutex_);
    measurePerformance_ = p;
  }

  void printTimers(const std::string & prefix) const;

  void resetTimers();

  void addAVOption(const std::string & key, const std::string & value)
  {
    Lock lock(mutex_);
    avOptions_.push_back({key, value});
  }

  static void findDecoders(
    const std::string & codec, std::vector<std::string> * hw_decoders,
    std::vector<std::string> * sw_decoders);

  static std::string findDecoders(const std::string & codec);

  // ------------------- deprecated functions ---------------
  [[deprecated(
    "use findDecoders(codec) now.")]] static const std::unordered_map<std::string, std::string> &
  getDefaultEncoderToDecoderMap();

private:
  using Lock = std::unique_lock<std::mutex>;
  bool doInitDecoder(const std::string & encoding, const std::string & decoder);
  bool initDecoder(const std::string & encoding, const std::string & decoders);
  int receiveFrame();
  int convertFrameToMessage(const AVFrame * frame, const ImagePtr & image);
  void setAVOption(const std::string & field, const std::string & value);
  void setEncoding(const std::string & encoding);
  void resetNoLock();
  // --------------- variables
  rclcpp::Logger logger_;
  Callback callback_;
  PTSMap ptsToStamp_;
  std::vector<std::pair<std::string, std::string>> avOptions_;
  mutable std::mutex mutex_;
  // --- performance analysis
  bool measurePerformance_{false};
  TDiff tdiffTotal_;
  // --- libav related variables
  AVRational timeBase_{1, 100};
  std::string packetEncoding_;
  std::string origEncoding_;
  AVCodecContext * codecContext_{NULL};
  AVFrame * swFrame_{NULL};
  AVFrame * cpuFrame_{NULL};
  AVFrame * outputFrame_{NULL};
  SwsContext * swsContext_{NULL};
  enum AVPixelFormat hwPixFormat_ { AV_PIX_FMT_NONE };
  std::string outputMsgEncoding_;
  AVPacket packet_;
  AVBufferRef * hwDeviceContext_{NULL};
};
}  // namespace ffmpeg_encoder_decoder

#endif  // FFMPEG_ENCODER_DECODER__DECODER_HPP_