27     #include <libavcodec/avcodec.h> 
   28     #include <libavformat/avformat.h> 
   29     #if USE_AVCODEC_GREATER_THAN_58_134 
   30         #include <libavcodec/bsf.h> 
   49     SEEK_MODE_EXACT_FRAME = 0,
 
   50     SEEK_MODE_PREV_KEY_FRAME = 1,
 
   59     SEEK_CRITERIA_FRAME_NUM = 0,
 
   60     SEEK_CRITERIA_TIME_STAMP = 1,
 
   77         : use_seek_(
false), seek_frame_(0), seek_mode_(SEEK_MODE_PREV_KEY_FRAME), seek_crit_(SEEK_CRITERIA_FRAME_NUM),
 
   78         out_frame_pts_(0), out_frame_duration_(0), num_frames_decoded_(0U) {}
 
   81         : use_seek_(
true), seek_frame_(frame_id), seek_mode_(SEEK_MODE_PREV_KEY_FRAME),
 
   82         seek_crit_(SEEK_CRITERIA_FRAME_NUM), out_frame_pts_(0), out_frame_duration_(0), num_frames_decoded_(0U) {}
 
   85         use_seek_ = other.use_seek_;
 
   86         seek_frame_ = other.seek_frame_;
 
   87         seek_mode_ = other.seek_mode_;
 
   88         seek_crit_ = other.seek_crit_;
 
   89         out_frame_pts_ = other.out_frame_pts_;
 
   90         out_frame_duration_ = other.out_frame_duration_;
 
   91         num_frames_decoded_ = other.num_frames_decoded_;
 
  102     uint64_t seek_frame_;
 
  111     int64_t out_frame_pts_;
 
  114     int64_t out_frame_duration_;
 
  117     uint64_t num_frames_decoded_;
 
  120     int64_t requested_frame_pts_;
 
  130                 virtual int GetData(uint8_t *buf, 
int buf_size) = 0;
 
  131                 virtual size_t GetBufferSize() = 0;
 
  133         AVCodecID GetCodecID() { 
return av_video_codec_id_; };
 
  135         VideoDemuxer(StreamProvider *stream_provider) : 
VideoDemuxer(CreateFmtContextUtil(stream_provider)) {av_io_ctx_ = av_fmt_input_ctx_->pb;}
 
  137             if (!av_fmt_input_ctx_) {
 
  141                 av_packet_free(&packet_);
 
  143             if (packet_filtered_) {
 
  144                 av_packet_free(&packet_filtered_);
 
  147                 av_bsf_free(&av_bsf_ctx_);
 
  149             avformat_close_input(&av_fmt_input_ctx_);
 
  151                 av_freep(&av_io_ctx_->buffer);
 
  152                 av_freep(&av_io_ctx_);
 
  154             if (data_with_header_) {
 
  155                 av_free(data_with_header_);
 
  158         bool Demux(uint8_t **video, 
int *video_size, int64_t *pts = 
nullptr) {
 
  159             if (!av_fmt_input_ctx_) {
 
  164                 av_packet_unref(packet_);
 
  167             while ((ret = av_read_frame(av_fmt_input_ctx_, packet_)) >= 0 && packet_->stream_index != av_stream_) {
 
  168                 av_packet_unref(packet_);
 
  173             if (is_h264_ || is_hevc_) {
 
  174                 if (packet_filtered_->data) {
 
  175                     av_packet_unref(packet_filtered_);
 
  177                 if (av_bsf_send_packet(av_bsf_ctx_, packet_) != 0) {
 
  178                     std::cerr << 
"ERROR: av_bsf_send_packet failed!" << std::endl;
 
  181                 if (av_bsf_receive_packet(av_bsf_ctx_, packet_filtered_) != 0) {
 
  182                     std::cerr << 
"ERROR: av_bsf_receive_packet failed!" << std::endl;
 
  185                 *video = packet_filtered_->data;
 
  186                 *video_size = packet_filtered_->size;
 
  187                 if (packet_filtered_->dts != AV_NOPTS_VALUE) {
 
  188                     pkt_dts_ = packet_filtered_->dts;
 
  190                     pkt_dts_ = packet_filtered_->pts;
 
  193                     *pts = (int64_t) (packet_filtered_->pts * default_time_scale_ * time_base_);
 
  194                     pkt_duration_ = packet_filtered_->duration;
 
  197                 if (is_mpeg4_ && (frame_count_ == 0)) {
 
  198                     int ext_data_size = av_fmt_input_ctx_->streams[av_stream_]->codecpar->extradata_size;
 
  199                     if (ext_data_size > 0) {
 
  200                         data_with_header_ = (uint8_t *)av_malloc(ext_data_size + packet_->size - 3 * 
sizeof(uint8_t));
 
  201                         if (!data_with_header_) {
 
  202                             std::cerr << 
"ERROR: av_malloc failed!" << std::endl;
 
  205                         memcpy(data_with_header_, av_fmt_input_ctx_->streams[av_stream_]->codecpar->extradata, ext_data_size);
 
  206                         memcpy(data_with_header_ + ext_data_size, packet_->data + 3, packet_->size - 3 * 
sizeof(uint8_t));
 
  207                         *video = data_with_header_;
 
  208                         *video_size = ext_data_size + packet_->size - 3 * 
sizeof(uint8_t);
 
  211                     *video = packet_->data;
 
  212                     *video_size = packet_->size;
 
  214                 if (packet_->dts != AV_NOPTS_VALUE) {
 
  215                     pkt_dts_ = packet_->dts;
 
  217                     pkt_dts_ = packet_->pts;
 
  220                     *pts = (int64_t)(packet_->pts * default_time_scale_ * time_base_);
 
  221                     pkt_duration_ = packet_->duration;
 
  227         bool Seek(
VideoSeekContext& seek_ctx, uint8_t** pp_video, 
int* video_size) {
 
  236                 std::cerr << 
"ERROR: Seek isn't supported for this input." << std::endl;
 
  240             if (IsVFR() && (SEEK_CRITERIA_FRAME_NUM == seek_ctx.seek_crit_)) {
 
  241                 std::cerr << 
"ERROR: Can't seek by frame number in VFR sequences. Seek by timestamp instead." << std::endl;
 
  244             int64_t timestamp = 0;
 
  247                 bool seek_backward = 
true;
 
  250                 switch (seek_ctx.seek_crit_) {
 
  251                     case SEEK_CRITERIA_FRAME_NUM:
 
  252                         timestamp = TsFromFrameNumber(seek_ctx.seek_frame_);
 
  253                         ret = av_seek_frame(av_fmt_input_ctx_, av_stream_, timestamp, seek_backward ? AVSEEK_FLAG_BACKWARD | flags : flags);
 
  255                     case SEEK_CRITERIA_TIME_STAMP:
 
  256                         timestamp = TsFromTime(seek_ctx.seek_frame_);
 
  257                         ret = av_seek_frame(av_fmt_input_ctx_, av_stream_, timestamp, seek_backward ? AVSEEK_FLAG_BACKWARD | flags : flags);
 
  260                         std::cerr << 
"ERROR: Invalid seek mode" << std::endl;
 
  265                     throw std::runtime_error(
"ERROR: seeking for frame");
 
  271                 int64_t target_ts = 0;
 
  273                 switch (seek_ctx.seek_crit_) {
 
  274                     case SEEK_CRITERIA_FRAME_NUM:
 
  275                         target_ts = TsFromFrameNumber(seek_ctx.seek_frame_);
 
  277                     case SEEK_CRITERIA_TIME_STAMP:
 
  278                         target_ts = TsFromTime(seek_ctx.seek_frame_);
 
  281                         std::cerr << 
"ERROR::Invalid seek criteria" << std::endl;
 
  285                 if (pkt_dts_ == target_ts) {
 
  287                 } 
else if (pkt_dts_ > target_ts) {
 
  299                 seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
 
  303                     if (!Demux(pp_video, video_size, &pkt_data.pts)) {
 
  304                         throw std::runtime_error(
"ERROR: Demux failed trying to seek for specified frame number/timestamp");
 
  306                     seek_done = is_seek_done(pkt_data, seek_ctx);
 
  309                         if ((tmp_ctx.seek_frame_--) >= 0) {
 
  310                             seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
 
  312                     } 
else if (seek_done < 0) { 
 
  313                         tmp_ctx.seek_frame_++;
 
  314                         seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
 
  316                     if (tmp_ctx.seek_frame_ == seek_ctx.seek_frame_) 
 
  318                 } 
while (seek_done != 0);
 
  320                 seek_ctx.out_frame_pts_ = pkt_data.pts;
 
  321                 seek_ctx.out_frame_duration_ = pkt_data.duration = pkt_duration_;
 
  322                 seek_ctx.requested_frame_pts_ = (int64_t) (timestamp * default_time_scale_ * time_base_);
 
  327                 seek_frame(seek_ctx, AVSEEK_FLAG_BACKWARD);
 
  328                 Demux(pp_video, video_size, &pkt_data.pts);
 
  329                 seek_ctx.num_frames_decoded_ = 
static_cast<uint64_t
>(pkt_data.pts / 1000 * frame_rate_);
 
  330                 seek_ctx.out_frame_pts_ = pkt_data.pts;
 
  331                 seek_ctx.out_frame_duration_ = pkt_data.duration = pkt_duration_;
 
  332                 seek_ctx.requested_frame_pts_ = (int64_t) (timestamp * default_time_scale_ * time_base_);
 
  336             pktData.bsl_data = size_t(*pp_video);
 
  337             pktData.bsl = *video_size;
 
  339             switch (seek_ctx.seek_mode_) {
 
  340             case SEEK_MODE_EXACT_FRAME:
 
  341                 seek_for_exact_frame(pktData, seek_ctx);
 
  343             case SEEK_MODE_PREV_KEY_FRAME:
 
  344                 seek_for_prev_key_frame(pktData, seek_ctx);
 
  347                 throw std::runtime_error(
"ERROR::Unsupported seek mode");
 
  353         const uint32_t GetWidth()
 const { 
return width_;}
 
  354         const uint32_t GetHeight()
 const { 
return height_;}
 
  355         const uint32_t GetChromaHeight()
 const { 
return chroma_height_;}
 
  356         const uint32_t GetBitDepth()
 const { 
return bit_depth_;}
 
  357         const uint32_t GetBytePerPixel()
 const { 
return byte_per_pixel_;}
 
  358         const uint32_t GetBitRate()
 const { 
return bit_rate_;}
 
  359         const double GetFrameRate()
 const {
return frame_rate_;};
 
  360         bool IsVFR()
 const { 
return frame_rate_ != avg_frame_rate_; };
 
  361         int64_t TsFromTime(
double ts_sec) {
 
  363             auto const ts_tbu = llround(ts_sec * AV_TIME_BASE);
 
  365             AVRational time_factor = {1, AV_TIME_BASE};
 
  366             return av_rescale_q(ts_tbu, time_factor, av_fmt_input_ctx_->streams[av_stream_]->time_base);
 
  369         int64_t TsFromFrameNumber(int64_t frame_num) {
 
  370             auto const ts_sec = 
static_cast<double>(frame_num) / frame_rate_;
 
  371             return TsFromTime(ts_sec);
 
  375         VideoDemuxer(AVFormatContext *av_fmt_input_ctx) : av_fmt_input_ctx_(av_fmt_input_ctx) {
 
  376             av_log_set_level(AV_LOG_QUIET);
 
  377             if (!av_fmt_input_ctx_) {
 
  378                 std::cerr << 
"ERROR: av_fmt_input_ctx_ is not vaild!" << std::endl;
 
  381             packet_ = av_packet_alloc();
 
  382             packet_filtered_ = av_packet_alloc();
 
  383             if (!packet_ || !packet_filtered_) {
 
  384                 std::cerr << 
"ERROR: av_packet_alloc failed!" << std::endl;
 
  387             if (avformat_find_stream_info(av_fmt_input_ctx_, 
nullptr) < 0) {
 
  388                 std::cerr << 
"ERROR: avformat_find_stream_info failed!" << std::endl;
 
  391             av_stream_ = av_find_best_stream(av_fmt_input_ctx_, AVMEDIA_TYPE_VIDEO, -1, -1, 
nullptr, 0);
 
  392             if (av_stream_ < 0) {
 
  393                 std::cerr << 
"ERROR: av_find_best_stream failed!" << std::endl;
 
  394                 av_packet_free(&packet_);
 
  395                 av_packet_free(&packet_filtered_);
 
  398             av_video_codec_id_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->codec_id;
 
  399             width_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->width;
 
  400             height_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->height;
 
  401             chroma_format_ = (AVPixelFormat)av_fmt_input_ctx_->streams[av_stream_]->codecpar->format;
 
  402             bit_rate_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->bit_rate;
 
  403             if (av_fmt_input_ctx_->streams[av_stream_]->r_frame_rate.den != 0)
 
  404                 frame_rate_ = 
static_cast<double>(av_fmt_input_ctx_->streams[av_stream_]->r_frame_rate.num) / 
static_cast<double>(av_fmt_input_ctx_->streams[av_stream_]->r_frame_rate.den);
 
  405             if (av_fmt_input_ctx_->streams[av_stream_]->avg_frame_rate.den != 0)
 
  406                 avg_frame_rate_ = 
static_cast<double>(av_fmt_input_ctx_->streams[av_stream_]->avg_frame_rate.num) / 
static_cast<double>(av_fmt_input_ctx_->streams[av_stream_]->avg_frame_rate.den);
 
  408             switch (chroma_format_) {
 
  409                 case AV_PIX_FMT_YUV420P10LE:
 
  410                 case AV_PIX_FMT_GRAY10LE:
 
  412                     chroma_height_ = (height_ + 1) >> 1;
 
  415                 case AV_PIX_FMT_YUV420P12LE:
 
  417                     chroma_height_ = (height_ + 1) >> 1;
 
  420                 case AV_PIX_FMT_YUV444P10LE:
 
  422                     chroma_height_ = height_ << 1;
 
  425                 case AV_PIX_FMT_YUV444P12LE:
 
  427                     chroma_height_ = height_ << 1;
 
  430                 case AV_PIX_FMT_YUV444P:
 
  432                     chroma_height_ = height_ << 1;
 
  435                 case AV_PIX_FMT_YUV420P:
 
  436                 case AV_PIX_FMT_YUVJ420P:
 
  437                 case AV_PIX_FMT_YUVJ422P:
 
  438                 case AV_PIX_FMT_YUVJ444P:
 
  439                 case AV_PIX_FMT_GRAY8:
 
  441                     chroma_height_ = (height_ + 1) >> 1;
 
  445                     chroma_format_ = AV_PIX_FMT_YUV420P;
 
  447                     chroma_height_ = (height_ + 1) >> 1;
 
  451             AVRational time_base = av_fmt_input_ctx_->streams[av_stream_]->time_base;
 
  452             time_base_ = av_q2d(time_base);
 
  454             is_h264_ = av_video_codec_id_ == AV_CODEC_ID_H264 && (!strcmp(av_fmt_input_ctx_->iformat->long_name, 
"QuickTime / MOV") 
 
  455                         || !strcmp(av_fmt_input_ctx_->iformat->long_name, 
"FLV (Flash Video)") 
 
  456                         || !strcmp(av_fmt_input_ctx_->iformat->long_name, 
"Matroska / WebM"));
 
  457             is_hevc_ = av_video_codec_id_ == AV_CODEC_ID_HEVC && (!strcmp(av_fmt_input_ctx_->iformat->long_name, 
"QuickTime / MOV")
 
  458                         || !strcmp(av_fmt_input_ctx_->iformat->long_name, 
"FLV (Flash Video)")
 
  459                         || !strcmp(av_fmt_input_ctx_->iformat->long_name, 
"Matroska / WebM"));
 
  460             is_mpeg4_ = av_video_codec_id_ == AV_CODEC_ID_MPEG4 && (!strcmp(av_fmt_input_ctx_->iformat->long_name, 
"QuickTime / MOV")
 
  461                         || !strcmp(av_fmt_input_ctx_->iformat->long_name, 
"FLV (Flash Video)")
 
  462                         || !strcmp(av_fmt_input_ctx_->iformat->long_name, 
"Matroska / WebM"));
 
  465 #if USE_AVCODEC_GREATER_THAN_58_134 
  468             is_seekable_ = av_fmt_input_ctx_->iformat->read_seek || av_fmt_input_ctx_->iformat->read_seek2;
 
  472                 const AVBitStreamFilter *bsf = av_bsf_get_by_name(
"h264_mp4toannexb");
 
  474                     std::cerr << 
"ERROR: av_bsf_get_by_name() failed" << std::endl;
 
  475                     av_packet_free(&packet_);
 
  476                     av_packet_free(&packet_filtered_);
 
  479                 if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0) {
 
  480                     std::cerr << 
"ERROR: av_bsf_alloc failed!" << std::endl;
 
  483                 avcodec_parameters_copy(av_bsf_ctx_->par_in, av_fmt_input_ctx_->streams[av_stream_]->codecpar);
 
  484                 if (av_bsf_init(av_bsf_ctx_) < 0) {
 
  485                     std::cerr << 
"ERROR: av_bsf_init failed!" << std::endl;
 
  490                 const AVBitStreamFilter *bsf = av_bsf_get_by_name(
"hevc_mp4toannexb");
 
  492                     std::cerr << 
"ERROR: av_bsf_get_by_name() failed" << std::endl;
 
  493                     av_packet_free(&packet_);
 
  494                     av_packet_free(&packet_filtered_);
 
  497                 if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0 ) {
 
  498                     std::cerr << 
"ERROR: av_bsf_alloc failed!" << std::endl;
 
  501                 avcodec_parameters_copy(av_bsf_ctx_->par_in, av_fmt_input_ctx_->streams[av_stream_]->codecpar);
 
  502                 if (av_bsf_init(av_bsf_ctx_) < 0) {
 
  503                     std::cerr << 
"ERROR: av_bsf_init failed!" << std::endl;
 
  508         AVFormatContext *CreateFmtContextUtil(StreamProvider *stream_provider) {
 
  509             AVFormatContext *ctx = 
nullptr;
 
  510             if (!(ctx = avformat_alloc_context())) {
 
  511                 std::cerr << 
"ERROR: avformat_alloc_context failed" << std::endl;
 
  514             uint8_t *avioc_buffer = 
nullptr;
 
  515             int avioc_buffer_size = stream_provider->GetBufferSize();
 
  516             avioc_buffer = (uint8_t *)av_malloc(avioc_buffer_size);
 
  518                 std::cerr << 
"ERROR: av_malloc failed!" << std::endl;
 
  521             av_io_ctx_ = avio_alloc_context(avioc_buffer, avioc_buffer_size,
 
  522                     0, stream_provider, &ReadPacket, 
nullptr, 
nullptr);
 
  524                 std::cerr << 
"ERROR: avio_alloc_context failed!" << std::endl;
 
  527             ctx->pb = av_io_ctx_;
 
  529             if (avformat_open_input(&ctx, 
nullptr, 
nullptr, 
nullptr) != 0) {
 
  530                 std::cerr << 
"ERROR: avformat_open_input failed!" << std::endl;
 
  535         AVFormatContext *CreateFmtContextUtil(
const char *input_file_path) {
 
  536             avformat_network_init();
 
  537             AVFormatContext *ctx = 
nullptr;
 
  538             if (avformat_open_input(&ctx, input_file_path, 
nullptr, 
nullptr) != 0 ) {
 
  539                 std::cerr << 
"ERROR: avformat_open_input failed!" << std::endl;
 
  544         static int ReadPacket(
void *data, uint8_t *buf, 
int buf_size) {
 
  545             return ((StreamProvider *)data)->GetData(buf, buf_size);
 
  547         AVFormatContext *av_fmt_input_ctx_ = 
nullptr;
 
  548         AVIOContext *av_io_ctx_ = 
nullptr;
 
  549         AVPacket* packet_ = 
nullptr;
 
  550         AVPacket* packet_filtered_ = 
nullptr;
 
  551         AVBSFContext *av_bsf_ctx_ = 
nullptr;
 
  552         AVCodecID av_video_codec_id_;
 
  553         AVPixelFormat chroma_format_;
 
  554         double frame_rate_ = 0.0;
 
  555         double avg_frame_rate_ = 0.0;
 
  556         uint8_t *data_with_header_ = 
nullptr;
 
  558         bool is_h264_ = 
false; 
 
  559         bool is_hevc_ = 
false;
 
  560         bool is_mpeg4_ = 
false;
 
  561         bool is_seekable_ = 
false;
 
  562         int64_t default_time_scale_ = 1000;
 
  563         double time_base_ = 0.0;
 
  564         uint32_t frame_count_ = 0;
 
  566         uint32_t height_ = 0;
 
  567         uint32_t chroma_height_ = 0;
 
  568         uint32_t bit_depth_ = 0;
 
  569         uint32_t byte_per_pixel_ = 0;
 
  570         uint32_t bit_rate_ = 0;
 
  572         int64_t pkt_dts_ = 0;
 
  573         int64_t pkt_duration_ = 0;
 
  576 static inline rocDecVideoCodec AVCodec2RocDecVideoCodec(AVCodecID av_codec) {
 
Definition: video_demuxer.h:127
 
Definition: video_demuxer.h:125
 
Definition: video_demuxer.h:74
 
The AMD rocDecode Library.
 
@ rocDecVideoCodec_AV1
Definition: rocdecode.h:83
 
@ rocDecVideoCodec_MPEG4
Definition: rocdecode.h:80
 
@ rocDecVideoCodec_HEVC
Definition: rocdecode.h:82
 
@ rocDecVideoCodec_MPEG1
Definition: rocdecode.h:78
 
@ rocDecVideoCodec_JPEG
Definition: rocdecode.h:86
 
@ rocDecVideoCodec_VP9
Definition: rocdecode.h:85
 
@ rocDecVideoCodec_AVC
Definition: rocdecode.h:81
 
@ rocDecVideoCodec_MPEG2
Definition: rocdecode.h:79
 
@ rocDecVideoCodec_VP8
Definition: rocdecode.h:84
 
@ rocDecVideoCodec_NumCodecs
Definition: rocdecode.h:87
 
Definition: video_demuxer.h:64
 
SeekModeEnum
Enum for Seek mode.
Definition: video_demuxer.h:48
 
enum SeekModeEnum SeekMode
Enum for Seek mode.
 
SeekCriteriaEnum
Enum for Seek Criteria.
Definition: video_demuxer.h:58
 
enum SeekCriteriaEnum SeekCriteria
Enum for Seek Criteria.