docs-7.0.0/utils/video_demuxer.h Source File

docs-7.0.0/utils/video_demuxer.h Source File#

rocDecode: docs-7.0.0/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/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  /* PTS of frame to seek as set by the user in seek_frame_. */
120  int64_t requested_frame_pts_;
121 };
122 
123 
124 // Video Demuxer Interface class
126  public:
128  public:
129  virtual ~StreamProvider() {}
130  virtual int GetData(uint8_t *buf, int buf_size) = 0;
131  virtual size_t GetBufferSize() = 0;
132  };
133  AVCodecID GetCodecID() { return av_video_codec_id_; };
134  VideoDemuxer(const char *input_file_path) : VideoDemuxer(CreateFmtContextUtil(input_file_path)) {}
135  VideoDemuxer(StreamProvider *stream_provider) : VideoDemuxer(CreateFmtContextUtil(stream_provider)) {av_io_ctx_ = av_fmt_input_ctx_->pb;}
136  ~VideoDemuxer() {
137  if (!av_fmt_input_ctx_) {
138  return;
139  }
140  if (packet_) {
141  av_packet_free(&packet_);
142  }
143  if (packet_filtered_) {
144  av_packet_free(&packet_filtered_);
145  }
146  if (av_bsf_ctx_) {
147  av_bsf_free(&av_bsf_ctx_);
148  }
149  avformat_close_input(&av_fmt_input_ctx_);
150  if (av_io_ctx_) {
151  av_freep(&av_io_ctx_->buffer);
152  av_freep(&av_io_ctx_);
153  }
154  if (data_with_header_) {
155  av_free(data_with_header_);
156  }
157  }
158  bool Demux(uint8_t **video, int *video_size, int64_t *pts = nullptr) {
159  if (!av_fmt_input_ctx_) {
160  return false;
161  }
162  *video_size = 0;
163  if (packet_->data) {
164  av_packet_unref(packet_);
165  }
166  int ret = 0;
167  while ((ret = av_read_frame(av_fmt_input_ctx_, packet_)) >= 0 && packet_->stream_index != av_stream_) {
168  av_packet_unref(packet_);
169  }
170  if (ret < 0) {
171  return false;
172  }
173  if (is_h264_ || is_hevc_) {
174  if (packet_filtered_->data) {
175  av_packet_unref(packet_filtered_);
176  }
177  if (av_bsf_send_packet(av_bsf_ctx_, packet_) != 0) {
178  std::cerr << "ERROR: av_bsf_send_packet failed!" << std::endl;
179  return false;
180  }
181  if (av_bsf_receive_packet(av_bsf_ctx_, packet_filtered_) != 0) {
182  std::cerr << "ERROR: av_bsf_receive_packet failed!" << std::endl;
183  return false;
184  }
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;
189  } else {
190  pkt_dts_ = packet_filtered_->pts;
191  }
192  if (pts) {
193  *pts = (int64_t) (packet_filtered_->pts * default_time_scale_ * time_base_);
194  pkt_duration_ = packet_filtered_->duration;
195  }
196  } else {
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;
203  return false;
204  }
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);
209  }
210  } else {
211  *video = packet_->data;
212  *video_size = packet_->size;
213  }
214  if (packet_->dts != AV_NOPTS_VALUE) {
215  pkt_dts_ = packet_->dts;
216  } else {
217  pkt_dts_ = packet_->pts;
218  }
219  if (pts) {
220  *pts = (int64_t)(packet_->pts * default_time_scale_ * time_base_);
221  pkt_duration_ = packet_->duration;
222  }
223  }
224  frame_count_++;
225  return true;
226  }
227  bool Seek(VideoSeekContext& seek_ctx, uint8_t** pp_video, int* video_size) {
228  /* !!! IMPORTANT !!!
229  * Across this function, packet decode timestamp (DTS) values are used to
230  * compare given timestamp against. This is done because DTS values shall
231  * monotonically increase during the course of decoding unlike PTS values
232  * which may be affected by frame reordering due to B frames.
233  */
234 
235  if (!is_seekable_) {
236  std::cerr << "ERROR: Seek isn't supported for this input." << std::endl;
237  return false;
238  }
239 
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;
242  return false;
243  }
244  int64_t timestamp = 0;
245  // Seek for single frame;
246  auto seek_frame = [&](VideoSeekContext const& seek_ctx, int flags) {
247  bool seek_backward = true;
248  int ret = 0;
249 
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);
254  break;
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);
258  break;
259  default:
260  std::cerr << "ERROR: Invalid seek mode" << std::endl;
261  ret = -1;
262  }
263 
264  if (ret < 0) {
265  throw std::runtime_error("ERROR: seeking for frame");
266  }
267  };
268 
269  // Check if frame satisfies seek conditions;
270  auto is_seek_done = [&](PacketData& pkt_data, VideoSeekContext const& seek_ctx) {
271  int64_t target_ts = 0;
272 
273  switch (seek_ctx.seek_crit_) {
274  case SEEK_CRITERIA_FRAME_NUM:
275  target_ts = TsFromFrameNumber(seek_ctx.seek_frame_);
276  break;
277  case SEEK_CRITERIA_TIME_STAMP:
278  target_ts = TsFromTime(seek_ctx.seek_frame_);
279  break;
280  default:
281  std::cerr << "ERROR::Invalid seek criteria" << std::endl;
282  return -1;
283  }
284 
285  if (pkt_dts_ == target_ts) {
286  return 0;
287  } else if (pkt_dts_ > target_ts) {
288  return 1;
289  } else {
290  return -1;
291  };
292  };
293 
294  /* This will seek for exact frame number;
295  * Note that decoder may not be able to decode such frame; */
296  auto seek_for_exact_frame = [&](PacketData& pkt_data, VideoSeekContext& seek_ctx) {
297  // Repetititive seek until seek condition is satisfied;
298  VideoSeekContext tmp_ctx(seek_ctx.seek_frame_);
299  seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
300 
301  int seek_done = 0;
302  do {
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");
305  }
306  seek_done = is_seek_done(pkt_data, seek_ctx);
307  //TODO: one last condition, check for a target too high than available for timestamp
308  if (seek_done > 0) { // We've gone too far and need to seek backwards;
309  if ((tmp_ctx.seek_frame_--) >= 0) {
310  seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
311  }
312  } else if (seek_done < 0) { // Need to read more frames until we reach requested number;
313  tmp_ctx.seek_frame_++;
314  seek_frame(tmp_ctx, AVSEEK_FLAG_ANY);
315  }
316  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
317  break;
318  } while (seek_done != 0);
319 
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_);
323  };
324 
325  // Seek for closest key frame in the past;
326  auto seek_for_prev_key_frame = [&](PacketData& pkt_data, VideoSeekContext& seek_ctx) {
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_);
333  };
334 
335  PacketData pktData;
336  pktData.bsl_data = size_t(*pp_video);
337  pktData.bsl = *video_size;
338 
339  switch (seek_ctx.seek_mode_) {
340  case SEEK_MODE_EXACT_FRAME:
341  seek_for_exact_frame(pktData, seek_ctx);
342  break;
343  case SEEK_MODE_PREV_KEY_FRAME:
344  seek_for_prev_key_frame(pktData, seek_ctx);
345  break;
346  default:
347  throw std::runtime_error("ERROR::Unsupported seek mode");
348  break;
349  }
350 
351  return true;
352  }
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) {
362  // Convert integer timestamp representation to AV_TIME_BASE and switch to fixed_point
363  auto const ts_tbu = llround(ts_sec * AV_TIME_BASE);
364  // Rescale the timestamp to value represented in stream base units;
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);
367  }
368 
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);
372  }
373 
374  private:
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;
379  return;
380  }
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;
385  return;
386  }
387  if (avformat_find_stream_info(av_fmt_input_ctx_, nullptr) < 0) {
388  std::cerr << "ERROR: avformat_find_stream_info failed!" << std::endl;
389  return;
390  }
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_);
396  return;
397  }
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);
407 
408  switch (chroma_format_) {
409  case AV_PIX_FMT_YUV420P10LE:
410  case AV_PIX_FMT_GRAY10LE:
411  bit_depth_ = 10;
412  chroma_height_ = (height_ + 1) >> 1;
413  byte_per_pixel_ = 2;
414  break;
415  case AV_PIX_FMT_YUV420P12LE:
416  bit_depth_ = 12;
417  chroma_height_ = (height_ + 1) >> 1;
418  byte_per_pixel_ = 2;
419  break;
420  case AV_PIX_FMT_YUV444P10LE:
421  bit_depth_ = 10;
422  chroma_height_ = height_ << 1;
423  byte_per_pixel_ = 2;
424  break;
425  case AV_PIX_FMT_YUV444P12LE:
426  bit_depth_ = 12;
427  chroma_height_ = height_ << 1;
428  byte_per_pixel_ = 2;
429  break;
430  case AV_PIX_FMT_YUV444P:
431  bit_depth_ = 8;
432  chroma_height_ = height_ << 1;
433  byte_per_pixel_ = 1;
434  break;
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:
440  bit_depth_ = 8;
441  chroma_height_ = (height_ + 1) >> 1;
442  byte_per_pixel_ = 1;
443  break;
444  default:
445  chroma_format_ = AV_PIX_FMT_YUV420P;
446  bit_depth_ = 8;
447  chroma_height_ = (height_ + 1) >> 1;
448  byte_per_pixel_ = 1;
449  }
450 
451  AVRational time_base = av_fmt_input_ctx_->streams[av_stream_]->time_base;
452  time_base_ = av_q2d(time_base);
453 
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"));
463 
464  // Check if the input file allow seek functionality.
465 #if USE_AVCODEC_GREATER_THAN_58_134
466  is_seekable_ = true; //for latest version of FFMPeg, read_seek and read_seek2 is not exposed in AVFormatContext
467 #else
468  is_seekable_ = av_fmt_input_ctx_->iformat->read_seek || av_fmt_input_ctx_->iformat->read_seek2;
469 #endif
470 
471  if (is_h264_) {
472  const AVBitStreamFilter *bsf = av_bsf_get_by_name("h264_mp4toannexb");
473  if (!bsf) {
474  std::cerr << "ERROR: av_bsf_get_by_name() failed" << std::endl;
475  av_packet_free(&packet_);
476  av_packet_free(&packet_filtered_);
477  return;
478  }
479  if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0) {
480  std::cerr << "ERROR: av_bsf_alloc failed!" << std::endl;
481  return;
482  }
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;
486  return;
487  }
488  }
489  if (is_hevc_) {
490  const AVBitStreamFilter *bsf = av_bsf_get_by_name("hevc_mp4toannexb");
491  if (!bsf) {
492  std::cerr << "ERROR: av_bsf_get_by_name() failed" << std::endl;
493  av_packet_free(&packet_);
494  av_packet_free(&packet_filtered_);
495  return;
496  }
497  if (av_bsf_alloc(bsf, &av_bsf_ctx_) != 0 ) {
498  std::cerr << "ERROR: av_bsf_alloc failed!" << std::endl;
499  return;
500  }
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;
504  return;
505  }
506  }
507  }
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;
512  return nullptr;
513  }
514  uint8_t *avioc_buffer = nullptr;
515  int avioc_buffer_size = stream_provider->GetBufferSize();
516  avioc_buffer = (uint8_t *)av_malloc(avioc_buffer_size);
517  if (!avioc_buffer) {
518  std::cerr << "ERROR: av_malloc failed!" << std::endl;
519  return nullptr;
520  }
521  av_io_ctx_ = avio_alloc_context(avioc_buffer, avioc_buffer_size,
522  0, stream_provider, &ReadPacket, nullptr, nullptr);
523  if (!av_io_ctx_) {
524  std::cerr << "ERROR: avio_alloc_context failed!" << std::endl;
525  return nullptr;
526  }
527  ctx->pb = av_io_ctx_;
528 
529  if (avformat_open_input(&ctx, nullptr, nullptr, nullptr) != 0) {
530  std::cerr << "ERROR: avformat_open_input failed!" << std::endl;
531  return nullptr;
532  }
533  return ctx;
534  }
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;
540  return nullptr;
541  }
542  return ctx;
543  }
544  static int ReadPacket(void *data, uint8_t *buf, int buf_size) {
545  return ((StreamProvider *)data)->GetData(buf, buf_size);
546  }
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;
557  int av_stream_ = 0;
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;
565  uint32_t width_ = 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;
571  // used for Seek Exact frame
572  int64_t pkt_dts_ = 0;
573  int64_t pkt_duration_ = 0;
574 };
575 
576 static inline rocDecVideoCodec AVCodec2RocDecVideoCodec(AVCodecID av_codec) {
577  switch (av_codec) {
578  case AV_CODEC_ID_MPEG1VIDEO : return rocDecVideoCodec_MPEG1;
579  case AV_CODEC_ID_MPEG2VIDEO : return rocDecVideoCodec_MPEG2;
580  case AV_CODEC_ID_MPEG4 : return rocDecVideoCodec_MPEG4;
581  case AV_CODEC_ID_H264 : return rocDecVideoCodec_AVC;
582  case AV_CODEC_ID_HEVC : return rocDecVideoCodec_HEVC;
583  case AV_CODEC_ID_VP8 : return rocDecVideoCodec_VP8;
584  case AV_CODEC_ID_VP9 : return rocDecVideoCodec_VP9;
585  case AV_CODEC_ID_MJPEG : return rocDecVideoCodec_JPEG;
586  case AV_CODEC_ID_AV1 : return rocDecVideoCodec_AV1;
587  default : return rocDecVideoCodec_NumCodecs;
588  }
589 }
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.