Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for memory video file in FramesDecoder #4184

Merged
merged 6 commits into from
Aug 24, 2022

Conversation

awolant
Copy link
Contributor

@awolant awolant commented Aug 22, 2022

Signed-off-by: Albert Wolant awolant@nvidia.com

Category:

New feature

Description:

Add support for video files kept in memory for FramesDecoder and FramesDecoderGpu.

Additional information:

Affected modules and functionalities:

FramesDecoder, FramesDecoderGpu and video tests

Key points relevant for the review:

Is this functionality enough for video inference plan?

Tests:

  • Existing tests apply
  • New tests added
    • Python tests
    • GTests
    • Benchmark
    • Other
  • N/A

Checklist

Documentation

  • Existing documentation applies
  • Documentation updated
    • Docstring
    • Doxygen
    • RST
    • Jupyter
    • Other
  • N/A

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: N/A

JIRA TASK: DALI-2957

Signed-off-by: Albert Wolant <awolant@nvidia.com>
Signed-off-by: Albert Wolant <awolant@nvidia.com>
@awolant
Copy link
Contributor Author

awolant commented Aug 22, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5707917]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5707917]: BUILD FAILED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5707917]: BUILD PASSED

Signed-off-by: Albert Wolant <awolant@nvidia.com>
Comment on lines +80 to +128
void FramesDecoderGpu::InitGpuDecoder() {
nvdecode_state_ = std::make_unique<NvDecodeState>();

InitBitStreamFilter();

filtered_packet_ = av_packet_alloc();
DALI_ENFORCE(filtered_packet_, "Could not allocate av packet");

auto codec_type = GetCodecType();

// Create nv decoder
CUVIDDECODECREATEINFO decoder_info;
memset(&decoder_info, 0, sizeof(CUVIDDECODECREATEINFO));

decoder_info.bitDepthMinus8 = 0;
decoder_info.ChromaFormat = cudaVideoChromaFormat_420;
decoder_info.CodecType = codec_type;
decoder_info.ulHeight = Height();
decoder_info.ulWidth = Width();
decoder_info.ulMaxHeight = Height();
decoder_info.ulMaxWidth = Width();
decoder_info.ulTargetHeight = Height();
decoder_info.ulTargetWidth = Width();
decoder_info.ulNumDecodeSurfaces = num_decode_surfaces_;
decoder_info.ulNumOutputSurfaces = 2;

CUDA_CALL(cuvidCreateDecoder(&nvdecode_state_->decoder, &decoder_info));

// Create nv parser
CUVIDPARSERPARAMS parser_info;
memset(&parser_info, 0, sizeof(CUVIDPARSERPARAMS));
parser_info.CodecType = codec_type;
parser_info.ulMaxNumDecodeSurfaces = num_decode_surfaces_;
parser_info.ulMaxDisplayDelay = 0;
parser_info.pUserData = this;
parser_info.pfnSequenceCallback = detail::process_video_sequence;
parser_info.pfnDecodePicture = detail::process_picture_decode;
parser_info.pfnDisplayPicture = nullptr;

CUDA_CALL(cuvidCreateVideoParser(&nvdecode_state_->parser, &parser_info));

// Init internal frame buffer
// TODO(awolant): Check, if continuous buffer would be faster
for (size_t i = 0; i < frame_buffer_.size(); ++i) {
frame_buffer_[i].frame_.resize(FrameSize());
frame_buffer_[i].pts_ = -1;
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added new constructor in this PR. This is a part that is common for both constructors, so I extracted it to a separate method.

@awolant awolant marked this pull request as ready for review August 23, 2022 08:17
@awolant
Copy link
Contributor Author

awolant commented Aug 23, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5717738]: BUILD STARTED

@szalpal szalpal self-assigned this Aug 23, 2022
@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5717738]: BUILD PASSED

Copy link
Member

@szalpal szalpal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've put couple of questions. I believe they do not block anything, so if changing anything would require major refactor, we would be OK without these changes.

bool is_vfr_ = false;

std::string filename_ = "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about making this string also optional? The rationale would be that when we have a video from memory it would not have a filename. Unless of course the existing implementation assumes, that the filename need to always be there, in that case I wouldn't bother with such "enhancement".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. After the constructor we use it only to report errors to let user know which file caused the error. I refactored this code a bit, so now we have a function that returns name of the file or "memory file" instead.

av_state_->ctx_ = avformat_alloc_context();
DALI_ENFORCE(av_state_->ctx_, "Could not alloc avformat context");

const int av_io_buffer_size = 32768;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this number come from?
And maybe write it as (1 << 15) so it's less magical?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was the value that FFMPEG sets as a default when you do not try to change that. I extracted it as a const field in the class, changed the value and added some comment.

return to_read;
}

int64_t MemoryVideoFile::Seek(int64_t new_position, int origin) {
Copy link
Collaborator

@banasraf banasraf Aug 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this arg named origin? As I understand it's a seeking method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to mode. Yes, this is the seeking method.


int Read(unsigned char *buffer, int buffer_size);

int64_t Seek(int64_t new_position, int origin);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any short docu explaining what is the second argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* @param memory_file Pointer to memory with video file data.
* @param memory_file_size Size of memory_file.
*/
explicit FramesDecoderGpu(char *memory_file, int memory_file_size, cudaStream_t stream = 0);
Copy link
Collaborator

@banasraf banasraf Aug 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using span instead of passing the pointer and size separately? (up to you)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

span is C++ 20

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually do have our own implementation of span, so you could use that one. But it's up to you.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is not dependent on DALI other then some error checking and reporting and I think it would be good to keep it this way. It might be useful to others, I think.

Signed-off-by: Albert Wolant <awolant@nvidia.com>
@awolant
Copy link
Contributor Author

awolant commented Aug 23, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5722994]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5722994]: BUILD FAILED

Signed-off-by: Albert Wolant <awolant@nvidia.com>
@awolant
Copy link
Contributor Author

awolant commented Aug 24, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5729182]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5729182]: BUILD FAILED

Signed-off-by: Albert Wolant <awolant@nvidia.com>
@awolant
Copy link
Contributor Author

awolant commented Aug 24, 2022

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5729429]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5729429]: BUILD FAILED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [5729429]: BUILD PASSED

@awolant awolant merged commit 29ba8a2 into NVIDIA:main Aug 24, 2022
@JanuszL JanuszL mentioned this pull request Jan 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants