develop/utils/video_demuxer.h Source File

develop/utils/video_demuxer.h Source File#

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