@@ -464,41 +464,46 @@ void SingleStreamDecoder::addStream(
464464
465465 codecContext->time_base = streamInfo.stream ->time_base ;
466466
467- // Initialize bitstream filter for H.264 MP4 containers
468- if (mediaType == AVMEDIA_TYPE_VIDEO &&
467+ // TODONVDEC probably best to extract-out the BSF logic in separate files.
468+ // Also need to handle more codecs. Pynvvideocodec also handles
469+ // AV_CODEC_ID_HEVC. Docs:
470+ // https://ffmpeg.org/doxygen/7.0/group__lavc__bsf.html
471+ if (deviceInterface_ && deviceInterface_->canDecodePacketDirectly () &&
472+ mediaType == AVMEDIA_TYPE_VIDEO &&
469473 codecContext->codec_id == AV_CODEC_ID_H264) {
470-
471- // Check if this is an MP4-style container that needs bitstream filtering
472- const char * formatName = formatContext_->iformat ->long_name ;
473- bool isMP4Container = (strcmp (formatName, " QuickTime / MOV" ) == 0 ||
474- strcmp (formatName, " FLV (Flash Video)" ) == 0 ||
475- strcmp (formatName, " Matroska / WebM" ) == 0 );
476-
477- if (isMP4Container) {
478- // printf("Initializing H.264 MP4 to Annex B bitstream filter for %s container\n", formatName);
479-
480- const AVBitStreamFilter* bsf = av_bsf_get_by_name (" h264_mp4toannexb" );
481- TORCH_CHECK (bsf != nullptr , " Failed to find h264_mp4toannexb bitstream filter" );
482-
483- AVBSFContext* rawBsf = nullptr ;
484- retVal = av_bsf_alloc (bsf, &rawBsf);
485- TORCH_CHECK (retVal >= AVSUCCESS, " Failed to allocate bitstream filter: " ,
486- getFFMPEGErrorStringFromErrorCode (retVal));
487-
488- streamInfo.bitstreamFilter .reset (rawBsf);
489-
490- retVal = avcodec_parameters_copy (streamInfo.bitstreamFilter ->par_in ,
491- streamInfo.stream ->codecpar );
492- TORCH_CHECK (retVal >= AVSUCCESS, " Failed to copy codec parameters: " ,
493- getFFMPEGErrorStringFromErrorCode (retVal));
494-
495- retVal = av_bsf_init (streamInfo.bitstreamFilter .get ());
496- TORCH_CHECK (retVal >= AVSUCCESS, " Failed to initialize bitstream filter: " ,
497- getFFMPEGErrorStringFromErrorCode (retVal));
498-
499- streamInfo.needsBitstreamFiltering = true ;
500- // printf("Successfully initialized bitstream filter\n");
501- }
474+ // TODONVDEC note that the pynvvideocodec implementation relies on this
475+ // check for setting up the BSF: bMp4H264 = eVideoCodec == AV_CODEC_ID_H264
476+ // && (
477+ // !strcmp(fmtc->iformat->long_name, "QuickTime / MOV")
478+ // || !strcmp(fmtc->iformat->long_name, "FLV (Flash Video)")
479+ // || !strcmp(fmtc->iformat->long_name, "Matroska / WebM")
480+ // );
481+
482+ const AVBitStreamFilter* avBSF = av_bsf_get_by_name (" h264_mp4toannexb" );
483+ TORCH_CHECK (
484+ avBSF != nullptr , " Failed to find h264_mp4toannexb bitstream filter" );
485+
486+ AVBSFContext* avBSFContext = nullptr ;
487+ retVal = av_bsf_alloc (avBSF, &avBSFContext);
488+ TORCH_CHECK (
489+ retVal >= AVSUCCESS,
490+ " Failed to allocate bitstream filter: " ,
491+ getFFMPEGErrorStringFromErrorCode (retVal));
492+
493+ streamInfo.bitstreamFilter .reset (avBSFContext);
494+
495+ retVal = avcodec_parameters_copy (
496+ streamInfo.bitstreamFilter ->par_in , streamInfo.stream ->codecpar );
497+ TORCH_CHECK (
498+ retVal >= AVSUCCESS,
499+ " Failed to copy codec parameters: " ,
500+ getFFMPEGErrorStringFromErrorCode (retVal));
501+
502+ retVal = av_bsf_init (streamInfo.bitstreamFilter .get ());
503+ TORCH_CHECK (
504+ retVal == AVSUCCESS,
505+ " Failed to initialize bitstream filter: " ,
506+ getFFMPEGErrorStringFromErrorCode (retVal));
502507 }
503508 containerMetadata_.allStreamMetadata [activeStreamIndex_].codecName =
504509 std::string (avcodec_get_name (codecContext->codec_id ));
@@ -1215,27 +1220,31 @@ UniqueAVFrame SingleStreamDecoder::decodeAVFrame(
12151220 ReferenceAVPacket* packetToSend = &packet;
12161221 AutoAVPacket filteredAutoPacket;
12171222 ReferenceAVPacket filteredPacket (filteredAutoPacket);
1218-
1223+
12191224 // Apply bitstream filtering if needed
1220- if (streamInfo.needsBitstreamFiltering && streamInfo.bitstreamFilter ) {
1221- // Send packet to bitstream filter
1222- int retVal = av_bsf_send_packet (streamInfo.bitstreamFilter .get (), packet.get ());
1223- TORCH_CHECK (retVal >= AVSUCCESS, " Failed to send packet to bitstream filter: " ,
1224- getFFMPEGErrorStringFromErrorCode (retVal));
1225-
1226- // Receive filtered packet
1227- retVal = av_bsf_receive_packet (streamInfo.bitstreamFilter .get (), filteredPacket.get ());
1228- TORCH_CHECK (retVal >= AVSUCCESS, " Failed to receive packet from bitstream filter: " ,
1229- getFFMPEGErrorStringFromErrorCode (retVal));
1230-
1225+ if (streamInfo.bitstreamFilter != nullptr ) {
1226+ int retVal =
1227+ av_bsf_send_packet (streamInfo.bitstreamFilter .get (), packet.get ());
1228+ TORCH_CHECK (
1229+ retVal >= AVSUCCESS,
1230+ " Failed to send packet to bitstream filter: " ,
1231+ getFFMPEGErrorStringFromErrorCode (retVal));
1232+
1233+ retVal = av_bsf_receive_packet (
1234+ streamInfo.bitstreamFilter .get (), filteredPacket.get ());
1235+ TORCH_CHECK (
1236+ retVal >= AVSUCCESS,
1237+ " Failed to receive packet from bitstream filter: " ,
1238+ getFFMPEGErrorStringFromErrorCode (retVal));
1239+
12311240 packetToSend = &filteredPacket;
12321241 }
1233-
1242+
12341243 // Use custom packet decoding (e.g., direct NVDEC)
12351244 UniqueAVFrame decodedFrame =
12361245 deviceInterface_->decodePacketDirectly (*packetToSend);
12371246 decodeStats_.numPacketsSentToDecoder ++;
1238-
1247+
12391248 if (decodedFrame && filterFunction (decodedFrame)) {
12401249 // We got the frame we're looking for from direct decoding
12411250 avFrame = std::move (decodedFrame);
0 commit comments