latest/utils/video_demuxer.h Source File

latest/utils/video_demuxer.h Source File#

rocDecode: latest/utils/video_demuxer.h Source File
video_demuxer.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2023 - 2025 Advanced Micro Devices, Inc. All rights reserved.
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 #pragma once
24 
25 #include <iostream>
26 extern "C" {
27  #include <libavcodec/avcodec.h>
28  #include <libavformat/avformat.h>
29  #if USE_AVCODEC_GREATER_THAN_58_134
30  #include <libavcodec/bsf.h>
31  #endif
32 }
33 
34 #include "rocdecode.h"
35 
48 typedef enum SeekModeEnum {
49  SEEK_MODE_EXACT_FRAME = 0,
50  SEEK_MODE_PREV_KEY_FRAME = 1,
51  SEEK_MODE_NUM,
53 
58 typedef enum SeekCriteriaEnum {
59  SEEK_CRITERIA_FRAME_NUM = 0,
60  SEEK_CRITERIA_TIME_STAMP = 1,
61  SEEK_CRITERIA_NUM,
63 
64 struct PacketData {
65  int32_t key;
66  int64_t pts;
67  int64_t dts;
68  uint64_t pos;
69  uintptr_t bsl_data;
70  uint64_t bsl;
71  uint64_t duration;
72 };
73 
75 public:
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) {}
79 
80  VideoSeekContext(uint64_t frame_id)
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) {}
83 
84  VideoSeekContext& operator=(const VideoSeekContext& other) {
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_;
92  return *this;
93  }
94 
95  /* Will be set to false when not seeking, true otherwise;
96  */
97  bool use_seek_;
98 
99  /* Frame we want to get. Set by user.
100  * Shall be set to frame timestamp in case seek is done by time.
101  */
102  uint64_t seek_frame_;
103 
104  /* Mode in which we seek. */
105  SeekMode seek_mode_;
106 
107  /* Criteria by which we seek. */
108  SeekCriteria seek_crit_;
109 
110  /* PTS of frame found after seek. */
111  int64_t out_frame_pts_;
112 
113  /* Duration of frame found after seek. */
114  int64_t out_frame_duration_;
115 
116  /* Number of frames that were decoded during seek. */
117  uint64_t num_frames_decoded_;
118 
119  /* DTS of frame found after seek.
120  * In case the requested frame is not seekable, the demuxer will seek
121  * to the nearest seekable frame and its DTS is stored in out_frame_dts_.
122  */
123  int64_t out_frame_dts_;
124 
125  /* DTS of frame to seek as set by the user in seek_frame_. */
126  int64_t requested_frame_dts_;
127 };
128 
129 
130 // Video Demuxer Interface class
132  public:
134  public:
135  virtual ~StreamProvider() {}
136  virtual int GetData(uint8_t *buf, int buf_size) = 0;
137  virtual size_t GetBufferSize() = 0;
138  };
139  AVCodecID GetCodecID() { return av_video_codec_id_; };
140  VideoDemuxer(const char *input_file_path) : VideoDemuxer(CreateFmtContextUtil(input_file_path)) {}
141  VideoDemuxer(StreamProvider *stream_provider) : VideoDemuxer(CreateFmtContextUtil(stream_provider)) {av_io_ctx_ = av_fmt_input_ctx_->pb;}
142  ~VideoDemuxer() {
143  if (!av_fmt_input_ctx_) {
144  return;
145  }
146  if (packet_) {
147  av_packet_free(&packet_);
148  }
149  if (packet_filtered_) {
150  av_packet_free(&packet_filtered_);
151  }
152  if (av_bsf_ctx_) {
153  av_bsf_free(&av_bsf_ctx_);
154  }
155  avformat_close_input(&av_fmt_input_ctx_);
156  if (av_io_ctx_) {
157  av_freep(&av_io_ctx_->buffer);
158  av_freep(&av_io_ctx_);
159  }
160  if (data_with_header_) {
161  av_free(data_with_header_);
162  }
163  }
164  bool Demux(uint8_t **video, int *video_size, int64_t *pts = nullptr, int64_t *dts = nullptr) {
165  if (!av_fmt_input_ctx_) {
166  return false;
167  }
168  *video_size = 0;
169  if (packet_->data) {
170  av_packet_unref(packet_);
171  }
172  int ret = 0;
173  while ((ret = av_read_frame(av_fmt_input_ctx_, packet_)) >= 0 && packet_->stream_index != av_stream_) {
174  av_packet_unref(packet_);
175  }
176  if (ret < 0) {
177  return false;
178  }
179  if (is_h264_ || is_hevc_) {
180  if (packet_filtered_->data) {
181  av_packet_unref(packet_filtered_);
182  }
183  if (av_bsf_send_packet(av_bsf_ctx_, packet_) != 0) {
184  std::cerr << "ERROR: av_bsf_send_packet failed!" << std::endl;
185  return false;
186  }
187  if (av_bsf_receive_packet(av_bsf_ctx_, packet_filtered_) != 0) {
188  std::cerr << "ERROR: av_bsf_receive_packet failed!" << std::endl;
189  return false;
190  }
191  *video = packet_filtered_->data;
192  *video_size = packet_filtered_->size;
193  if (packet_filtered_->dts != AV_NOPTS_VALUE) {
194  pkt_dts_ = packet_filtered_->dts;
195  } else {
196  pkt_dts_ = packet_filtered_->pts;
197  }
198  if (pts) {
199  *pts = (int64_t) (packet_filtered_->pts * default_time_scale_ * time_base_);
200  pkt_duration_ = packet_filtered_->duration;
201  }
202  if (dts) *dts = pkt_dts_;
203  } else {
204  if (is_mpeg4_ && (frame_count_ == 0)) {
205  int ext_data_size = av_fmt_input_ctx_->streams[av_stream_]->codecpar->extradata_size;
206  if (ext_data_size > 0) {
207  data_with_header_ = (uint8_t *)av_malloc(ext_data_size + packet_->size - 3 * sizeof(uint8_t));
208  if (!data_with_header_) {
209  std::cerr << "ERROR: av_malloc failed!" << std::endl;
210  return false;
211  }
212  memcpy(data_with_header_, av_fmt_input_ctx_->streams[av_stream_]->codecpar->extradata, ext_data_size);
213  memcpy(data_with_header_ + ext_data_size, packet_->data + 3, packet_->size - 3 * sizeof(uint8_t));
214  *video = data_with_header_;
215  *video_size = ext_data_size + packet_->size - 3 * sizeof(uint8_t);
216  }
217  } else {
218  *video = packet_->data;
219  *video_size = packet_->size;
220  }
221  if (packet_->dts != AV_NOPTS_VALUE) {
222  pkt_dts_ = packet_->dts;
223  } else {
224  pkt_dts_ = packet_->pts;
225  }
226  if (pts) {
227  *pts = (int64_t)(packet_->pts * default_time_scale_ * time_base_);
228  pkt_duration_ = packet_->duration;
229  }
230  if (dts) *dts = pkt_dts_;
231  }
232  frame_count_++;
233  return true;
234  }
235  bool Seek(VideoSeekContext& seek_ctx, uint8_t** pp_video, int* video_size) {
236  /* !!! IMPORTANT !!!
237  * Across this function, packet decode timestamp (DTS) values are used to
238  * compare given timestamp against. This is done because DTS values shall
239  * monotonically increase during the course of decoding unlike PTS values
240  * which may be affected by frame reordering due to B frames.
241  */
242 
243  if (!is_seekable_) {
244  std::cerr << "ERROR: Seek isn't supported for this input." << std::endl;
245  return false;
246  }
247 
248  if (IsVFR() && (SEEK_CRITERIA_FRAME_NUM == seek_ctx.seek_crit_)) {
249  std::cerr << "ERROR: Can't seek by frame number in VFR sequences. Seek by timestamp instead." << std::endl;
250  return false;
251  }
252 
253  int64_t timestamp = 0;
254  // Seek for single frame;
255  auto seek_frame = [&](VideoSeekContext const& seek_ctx, int flags) {
256  bool seek_backward = true;
257  int ret = 0;
258 
259  switch (seek_ctx.seek_crit_) {
260  case SEEK_CRITERIA_FRAME_NUM:
261  timestamp = TsFromFrameNumber(seek_ctx.seek_frame_);
262  ret = av_seek_frame(av_fmt_input_ctx_, av_stream_, timestamp, seek_backward ? AVSEEK_FLAG_BACKWARD | flags : flags);
263  break;
264  case SEEK_CRITERIA_TIME_STAMP:
265  timestamp = TsFromTime(seek_ctx.seek_frame_);
266  ret = av_seek_frame(av_fmt_input_ctx_, av_stream_, timestamp, seek_backward ? AVSEEK_FLAG_BACKWARD | flags : flags);
267  break;
268  default:
269  std::cerr << "ERROR: Invalid seek mode" << std::endl;
270  ret = -1;
271  }
272 
273  if (ret < 0) {
274  throw std::runtime_error("ERROR: seeking for frame");
275  }
276  };
277 
278  // Check if frame satisfies seek conditions;
279  auto is_seek_done = [&](PacketData& pkt_data, VideoSeekContext const& seek_ctx) {
280  int64_t target_ts = 0;
281 
282  switch (seek_ctx.seek_crit_) {
283  case SEEK_CRITERIA_FRAME_NUM:
284  target_ts = TsFromFrameNumber(seek_ctx.seek_frame_);
285  break;
286  case SEEK_CRITERIA_TIME_STAMP:
287  target_ts = TsFromTime(seek_ctx.seek_frame_);
288  break;
289  default:
290  std::cerr << "ERROR::Invalid seek criteria" << std::endl;
291  return -1;
292  }
293 
294  if (pkt_dts_ == target_ts) {
295  return 0;
296  } else if (pkt_dts_ > target_ts) {
297  return 1;
298  } else {
299  return -1;
300  };
301  };
302 
303  /* This will seek for exact frame number;
304  * Note that decoder may not be able to decode such frame; */
305  auto seek_for_exact_frame = [&](PacketData& pkt_data, VideoSeekContext& seek_ctx) {
306  // Repetititive seek until seek condition is satisfied;
307  VideoSeekContext tmp_ctx(seek_ctx.seek_frame_);
308  seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
309 
310  int seek_done = 0;
311  do {
312  if (!Demux(pp_video, video_size, &pkt_data.pts, &pkt_data.dts)) {
313  throw std::runtime_error("ERROR: Demux failed trying to seek for specified frame number/timestamp");
314  }
315  seek_done = is_seek_done(pkt_data, seek_ctx);
316  //TODO: one last condition, check for a target too high than available for timestamp
317  if (seek_done > 0) { // We've gone too far and need to seek backwards;
318  if ((tmp_ctx.seek_frame_--) >= 0) {
319  seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
320  }
321  } else if (seek_done < 0) { // Need to read more frames until we reach requested number;
322  tmp_ctx.seek_frame_++;
323  seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
324  }
325  if (tmp_ctx.seek_frame_ == seek_ctx.seek_frame_) // if frame 'N' is too far and frame 'N-1' is too less from target. Avoids infinite loop between N & N-1
326  break;
327  } while (seek_done != 0);
328 
329  seek_ctx.out_frame_pts_ = pkt_data.pts;
330  seek_ctx.out_frame_dts_ = pkt_data.dts;
331  seek_ctx.requested_frame_dts_ = timestamp;
332  seek_ctx.out_frame_duration_ = pkt_data.duration = pkt_duration_;
333  };
334 
335  // Seek for closest key frame in the past;
336  auto seek_for_prev_key_frame = [&](PacketData& pkt_data, VideoSeekContext& seek_ctx) {
337  seek_frame(seek_ctx, AVSEEK_FLAG_BACKWARD);
338  Demux(pp_video, video_size, &pkt_data.pts, &pkt_data.dts);
339  seek_ctx.num_frames_decoded_ = static_cast<uint64_t>(pkt_data.pts / 1000 * frame_rate_);
340  seek_ctx.out_frame_pts_ = pkt_data.pts;
341  seek_ctx.out_frame_dts_ = pkt_data.dts;
342  seek_ctx.requested_frame_dts_ = timestamp;
343  seek_ctx.out_frame_duration_ = pkt_data.duration = pkt_duration_;
344  };
345 
346  PacketData pktData;
347  pktData.bsl_data = size_t(*pp_video);
348  pktData.bsl = *video_size;
349 
350  switch (seek_ctx.seek_mode_) {
351  case SEEK_MODE_EXACT_FRAME:
352  seek_for_exact_frame(pktData, seek_ctx);
353  break;
354  case SEEK_MODE_PREV_KEY_FRAME:
355  seek_for_prev_key_frame(pktData, seek_ctx);
356  break;
357  default:
358  throw std::runtime_error("ERROR::Unsupported seek mode");
359  break;
360  }
361 
362  return true;
363  }
364  const uint32_t GetWidth() const { return width_;}
365  const uint32_t GetHeight() const { return height_;}
366  const uint32_t GetChromaHeight() const { return chroma_height_;}
367  const uint32_t GetBitDepth() const { return bit_depth_;}
368  const uint32_t GetBytePerPixel() const { return byte_per_pixel_;}
369  const uint32_t GetBitRate() const { return bit_rate_;}
370  const double GetFrameRate() const {return frame_rate_;};
371  bool IsVFR() const { return frame_rate_ != avg_frame_rate_; };
372  int64_t TsFromTime(double ts_sec) {
373  // Convert integer timestamp representation to AV_TIME_BASE and switch to fixed_point
374  auto const ts_tbu = llround(ts_sec * AV_TIME_BASE);
375  // Rescale the timestamp to value represented in stream base units;
376  AVRational time_factor = {1, AV_TIME_BASE};
377  return av_rescale_q(ts_tbu, time_factor, av_fmt_input_ctx_->streams[av_stream_]->time_base);
378  }
379 
380  int64_t TsFromFrameNumber(int64_t frame_num) {
381  auto const ts_sec = static_cast<double>(frame_num) / frame_rate_;
382  return TsFromTime(ts_sec);
383  }
384 
385  private:
386  VideoDemuxer(AVFormatContext *av_fmt_input_ctx) : av_fmt_input_ctx_(av_fmt_input_ctx) {
387  av_log_set_level(AV_LOG_QUIET);
388  if (!av_fmt_input_ctx_) {
389  std::cerr << "ERROR: av_fmt_input_ctx_ is not vaild!" << std::endl;
390  return;
391  }
392  packet_ = av_packet_alloc();
393  packet_filtered_ = av_packet_alloc();
394  if (!packet_ || !packet_filtered_) {
395  std::cerr << "ERROR: av_packet_alloc failed!" << std::endl;
396  return;
397  }
398  if (avformat_find_stream_info(av_fmt_input_ctx_, nullptr) < 0) {
399  std::cerr << "ERROR: avformat_find_stream_info failed!" << std::endl;
400  return;
401  }
402  av_stream_ = av_find_best_stream(av_fmt_input_ctx_, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
403  if (av_stream_ < 0) {
404  std::cerr << "ERROR: av_find_best_stream failed!" << std::endl;
405  av_packet_free(&packet_);
406  av_packet_free(&packet_filtered_);
407  return;
408  }
409  av_video_codec_id_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->codec_id;
410  width_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->width;
411  height_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->height;
412  chroma_format_ = (AVPixelFormat)av_fmt_input_ctx_->streams[av_stream_]->codecpar->format;
413  bit_rate_ = av_fmt_input_ctx_->streams[av_stream_]->codecpar->bit_rate;
414  if (av_fmt_input_ctx_->streams[av_stream_]->r_frame_rate.den != 0)
415  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);
416  if (av_fmt_input_ctx_->streams[av_stream_]->avg_frame_rate.den != 0)
417  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);
418 
419  switch (chroma_format_) {
420  case AV_PIX_FMT_YUV420P10LE:
421  case AV_PIX_FMT_GRAY10LE:
422  bit_depth_ = 10;
423  chroma_height_ = (height_ + 1) >> 1;
424  byte_per_pixel_ = 2;
425  break;
426  case AV_PIX_FMT_YUV420P12LE:
427  bit_depth_ = 12;
428  chroma_height_ = (height_ + 1) >> 1;
429  byte_per_pixel_ = 2;
430  break;
431  case AV_PIX_FMT_YUV444P10LE:
432  bit_depth_ = 10;
433  chroma_height_ = height_ << 1;
434  byte_per_pixel_ = 2;
435  break;
436  case AV_PIX_FMT_YUV444P12LE:
437  bit_depth_ = 12;
438  chroma_height_ = height_ << 1;
439  byte_per_pixel_ = 2;
440  break;
441  case AV_PIX_FMT_YUV444P:
442  bit_depth_ = 8;
443  chroma_height_ = height_ << 1;
444  byte_per_pixel_ = 1;
445  break;
446  case AV_PIX_FMT_YUV420P:
447  case AV_PIX_FMT_YUVJ420P:
448  case AV_PIX_FMT_YUVJ422P:
449  case AV_PIX_FMT_YUVJ444P:
450  case AV_PIX_FMT_GRAY8:
451  bit_depth_ = 8;
452  chroma_height_ = (height_ + 1) >> 1;
453  byte_per_pixel_ = 1;
454  break;
455  default:
456  chroma_format_ = AV_PIX_FMT_YUV420P;
457  bit_depth_ = 8;
458  chroma_height_ = (height_ + 1) >> 1;
459  byte_per_pixel_ = 1;
460  }
461 
462  AVRational time_base = av_fmt_input_ctx_->streams[av_stream_]->time_base;
463  time_base_ = av_q2d(time_base);
464 
465  is_h264_ = av_video_codec_id_ == AV_CODEC_ID_H264 && (!strcmp(av_fmt_input_ctx_->iformat->long_name, "QuickTime / MOV")
466  || !strcmp(av_fmt_input_ctx_->iformat->long_name, "FLV (Flash Video)")
467  || !strcmp(av_fmt_input_ctx_->iformat->long_name, "Matroska / WebM"));
468  is_hevc_ = av_video_codec_id_ == AV_CODEC_ID_HEVC && (!strcmp(av_fmt_input_ctx_->iformat->long_name, "QuickTime / MOV")
469  || !strcmp(av_fmt_input_ctx_->iformat->long_name, "FLV (Flash Video)")
470  || !strcmp(av_fmt_input_ctx_->iformat->long_name, "Matroska / WebM"));
471  is_mpeg4_ = av_video_codec_id_ == AV_CODEC_ID_MPEG4 && (!strcmp(av_fmt_input_ctx_->iformat->long_name, "QuickTime / MOV")
472  || !strcmp(av_fmt_input_ctx_->iformat->long_name, "FLV (Flash Video)")
473  || !strcmp(av_fmt_input_ctx_->iformat->long_name, "Matroska / WebM"));
474 
475  // Check if the input file allow seek functionality.
476  is_seekable_ = av_fmt_input_ctx_->iformat->read_seek || av_fmt_input_ctx_->iformat->read_seek2;
477 
478  if (is_h264_) {
479  const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
480  if (!bsf) {
481  std::cerr << "ERROR: av_bsf_get_by_name() failed" << std::endl;
482  av_packet_free(&packet_);
483  av_packet_free(&packet_filtered_);
484  return;
485  }
486  if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0) {
487  std::cerr << "ERROR: av_bsf_alloc failed!" << std::endl;
488  return;
489  }
490  avcodec_parameters_copy(av_bsf_ctx_->par_in, av_fmt_input_ctx_->streams[av_stream_]->codecpar);
491  if (av_bsf_init(av_bsf_ctx_) < 0) {
492  std::cerr << "ERROR: av_bsf_init failed!" << std::endl;
493  return;
494  }
495  }
496  if (is_hevc_) {
497  const AVBitStreamFilter *bsf = av_bsf_get_by_name("hevc_mp4toannexb");
498  if (!bsf) {
499  std::cerr << "ERROR: av_bsf_get_by_name() failed" << std::endl;
500  av_packet_free(&packet_);
501  av_packet_free(&packet_filtered_);
502  return;
503  }
504  if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0 ) {
505  std::cerr << "ERROR: av_bsf_alloc failed!" << std::endl;
506  return;
507  }
508  avcodec_parameters_copy(av_bsf_ctx_->par_in, av_fmt_input_ctx_->streams[av_stream_]->codecpar);
509  if (av_bsf_init(av_bsf_ctx_) < 0) {
510  std::cerr << "ERROR: av_bsf_init failed!" << std::endl;
511  return;
512  }
513  }
514  }
515  AVFormatContext *CreateFmtContextUtil(StreamProvider *stream_provider) {
516  AVFormatContext *ctx = nullptr;
517  if (!(ctx = avformat_alloc_context())) {
518  std::cerr << "ERROR: avformat_alloc_context failed" << std::endl;
519  return nullptr;
520  }
521  uint8_t *avioc_buffer = nullptr;
522  int avioc_buffer_size = stream_provider->GetBufferSize();
523  avioc_buffer = (uint8_t *)av_malloc(avioc_buffer_size);
524  if (!avioc_buffer) {
525  std::cerr << "ERROR: av_malloc failed!" << std::endl;
526  return nullptr;
527  }
528  av_io_ctx_ = avio_alloc_context(avioc_buffer, avioc_buffer_size,
529  0, stream_provider, &ReadPacket, nullptr, nullptr);
530  if (!av_io_ctx_) {
531  std::cerr << "ERROR: avio_alloc_context failed!" << std::endl;
532  return nullptr;
533  }
534  ctx->pb = av_io_ctx_;
535 
536  if (avformat_open_input(&ctx, nullptr, nullptr, nullptr) != 0) {
537  std::cerr << "ERROR: avformat_open_input failed!" << std::endl;
538  return nullptr;
539  }
540  return ctx;
541  }
542  AVFormatContext *CreateFmtContextUtil(const char *input_file_path) {
543  avformat_network_init();
544  AVFormatContext *ctx = nullptr;
545  if (avformat_open_input(&ctx, input_file_path, nullptr, nullptr) != 0 ) {
546  std::cerr << "ERROR: avformat_open_input failed!" << std::endl;
547  return nullptr;
548  }
549  return ctx;
550  }
551  static int ReadPacket(void *data, uint8_t *buf, int buf_size) {
552  return ((StreamProvider *)data)->GetData(buf, buf_size);
553  }
554  AVFormatContext *av_fmt_input_ctx_ = nullptr;
555  AVIOContext *av_io_ctx_ = nullptr;
556  AVPacket* packet_ = nullptr;
557  AVPacket* packet_filtered_ = nullptr;
558  AVBSFContext *av_bsf_ctx_ = nullptr;
559  AVCodecID av_video_codec_id_;
560  AVPixelFormat chroma_format_;
561  double frame_rate_ = 0.0;
562  double avg_frame_rate_ = 0.0;
563  uint8_t *data_with_header_ = nullptr;
564  int av_stream_ = 0;
565  bool is_h264_ = false;
566  bool is_hevc_ = false;
567  bool is_mpeg4_ = false;
568  bool is_seekable_ = false;
569  int64_t default_time_scale_ = 1000;
570  double time_base_ = 0.0;
571  uint32_t frame_count_ = 0;
572  uint32_t width_ = 0;
573  uint32_t height_ = 0;
574  uint32_t chroma_height_ = 0;
575  uint32_t bit_depth_ = 0;
576  uint32_t byte_per_pixel_ = 0;
577  uint32_t bit_rate_ = 0;
578  // used for Seek Exact frame
579  int64_t pkt_dts_ = 0;
580  int64_t pkt_duration_ = 0;
581 };
582 
583 static inline rocDecVideoCodec AVCodec2RocDecVideoCodec(AVCodecID av_codec) {
584  switch (av_codec) {
585  case AV_CODEC_ID_MPEG1VIDEO : return rocDecVideoCodec_MPEG1;
586  case AV_CODEC_ID_MPEG2VIDEO : return rocDecVideoCodec_MPEG2;
587  case AV_CODEC_ID_MPEG4 : return rocDecVideoCodec_MPEG4;
588  case AV_CODEC_ID_H264 : return rocDecVideoCodec_AVC;
589  case AV_CODEC_ID_HEVC : return rocDecVideoCodec_HEVC;
590  case AV_CODEC_ID_VP8 : return rocDecVideoCodec_VP8;
591  case AV_CODEC_ID_VP9 : return rocDecVideoCodec_VP9;
592  case AV_CODEC_ID_MJPEG : return rocDecVideoCodec_JPEG;
593  case AV_CODEC_ID_AV1 : return rocDecVideoCodec_AV1;
594  default : return rocDecVideoCodec_NumCodecs;
595  }
596 }
Definition: video_demuxer.h:133
Definition: video_demuxer.h:131
Definition: video_demuxer.h:74
The AMD rocDecode Library.
@ rocDecVideoCodec_AV1
Definition: rocdecode.h:84
@ rocDecVideoCodec_MPEG4
Definition: rocdecode.h:81
@ rocDecVideoCodec_HEVC
Definition: rocdecode.h:83
@ rocDecVideoCodec_MPEG1
Definition: rocdecode.h:79
@ rocDecVideoCodec_JPEG
Definition: rocdecode.h:87
@ rocDecVideoCodec_VP9
Definition: rocdecode.h:86
@ rocDecVideoCodec_AVC
Definition: rocdecode.h:82
@ rocDecVideoCodec_MPEG2
Definition: rocdecode.h:80
@ rocDecVideoCodec_VP8
Definition: rocdecode.h:85
@ rocDecVideoCodec_NumCodecs
Definition: rocdecode.h:88
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.