/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-rocdecode/checkouts/latest/utils/video_demuxer.h Source File

/home/docs/checkouts/readthedocs.org/user_builds/advanced-micro-devices-rocdecode/checkouts/latest/utils/video_demuxer.h Source File#

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