Skip to content

Commit 11779a7

Browse files
committed
Merge branch 'main' of github.com:pytorch/torchcodec into renamingzzzz
2 parents 941d6a3 + 9a9d17c commit 11779a7

File tree

3 files changed

+64
-6
lines changed

3 files changed

+64
-6
lines changed

src/torchcodec/decoders/_core/FFMPEGCommon.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,25 @@
1010

1111
namespace facebook::torchcodec {
1212

13+
AutoAVPacket::AutoAVPacket() : avPacket_(av_packet_alloc()) {
14+
TORCH_CHECK(avPacket_ != nullptr, "Couldn't allocate avPacket.");
15+
}
16+
AutoAVPacket::~AutoAVPacket() {
17+
av_packet_free(&avPacket_);
18+
}
19+
20+
ReferenceAVPacket::ReferenceAVPacket(AutoAVPacket& shared)
21+
: avPacket_(shared.avPacket_) {}
22+
ReferenceAVPacket::~ReferenceAVPacket() {
23+
av_packet_unref(avPacket_);
24+
}
25+
AVPacket* ReferenceAVPacket::get() {
26+
return avPacket_;
27+
}
28+
AVPacket* ReferenceAVPacket::operator->() {
29+
return avPacket_;
30+
}
31+
1332
AVCodecOnlyUseForCallingAVFindBestStream
1433
makeAVCodecOnlyUseForCallingAVFindBestStream(const AVCodec* codec) {
1534
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 18, 100)

src/torchcodec/decoders/_core/FFMPEGCommon.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ using UniqueAVCodecContext = std::unique_ptr<
5757
Deleterp<AVCodecContext, void, avcodec_free_context>>;
5858
using UniqueAVFrame =
5959
std::unique_ptr<AVFrame, Deleterp<AVFrame, void, av_frame_free>>;
60-
using UniqueAVPacket =
61-
std::unique_ptr<AVPacket, Deleterp<AVPacket, void, av_packet_free>>;
6260
using UniqueAVFilterGraph = std::unique_ptr<
6361
AVFilterGraph,
6462
Deleterp<AVFilterGraph, void, avfilter_graph_free>>;
@@ -70,6 +68,44 @@ using UniqueAVIOContext = std::
7068
using UniqueSwsContext =
7169
std::unique_ptr<SwsContext, Deleter<SwsContext, void, sws_freeContext>>;
7270

71+
// These 2 classes share the same underlying AVPacket object. They are meant to
72+
// be used in tandem, like so:
73+
//
74+
// AutoAVPacket autoAVPacket; // <-- malloc for AVPacket happens here
75+
// while(...){
76+
// ReferenceAVPacket packet(autoAVPacket);
77+
// av_read_frame(..., packet.get()); <-- av_packet_ref() called by FFmpeg
78+
// } <-- av_packet_unref() called here
79+
//
80+
// This achieves a few desirable things:
81+
// - Memory allocation of the underlying AVPacket happens only once, when
82+
// autoAVPacket is created.
83+
// - av_packet_free() is called when autoAVPacket gets out of scope
84+
// - av_packet_unref() is automatically called when needed, i.e. at the end of
85+
// each loop iteration (or when hitting break / continue). This prevents the
86+
// risk of us forgetting to call it.
87+
class AutoAVPacket {
88+
friend class ReferenceAVPacket;
89+
90+
private:
91+
AVPacket* avPacket_;
92+
93+
public:
94+
AutoAVPacket();
95+
~AutoAVPacket();
96+
};
97+
98+
class ReferenceAVPacket {
99+
private:
100+
AVPacket* avPacket_;
101+
102+
public:
103+
ReferenceAVPacket(AutoAVPacket& shared);
104+
~ReferenceAVPacket();
105+
AVPacket* get();
106+
AVPacket* operator->();
107+
};
108+
73109
// av_find_best_stream is not const-correct before commit:
74110
// https://github.com/FFmpeg/FFmpeg/commit/46dac8cf3d250184ab4247809bc03f60e14f4c0c
75111
// which was released in FFMPEG version=5.0.3

src/torchcodec/decoders/_core/VideoDecoder.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,11 @@ void VideoDecoder::scanFileAndUpdateMetadataAndIndex() {
579579
return;
580580
}
581581

582+
AutoAVPacket autoAVPacket;
582583
while (true) {
583-
// Get the next packet.
584-
UniqueAVPacket packet(av_packet_alloc());
584+
ReferenceAVPacket packet(autoAVPacket);
585+
586+
// av_read_frame is a misleading name: it gets the next **packet**.
585587
int ffmpegStatus = av_read_frame(formatContext_.get(), packet.get());
586588

587589
if (ffmpegStatus == AVERROR_EOF) {
@@ -812,6 +814,7 @@ VideoDecoder::RawDecodedOutput VideoDecoder::getDecodedOutputWithFilter(
812814
}
813815
// Need to get the next frame or error from PopFrame.
814816
UniqueAVFrame avFrame(av_frame_alloc());
817+
AutoAVPacket autoAVPacket;
815818
int ffmpegStatus = AVSUCCESS;
816819
bool reachedEOF = false;
817820
int frameStreamIndex = -1;
@@ -851,7 +854,7 @@ VideoDecoder::RawDecodedOutput VideoDecoder::getDecodedOutputWithFilter(
851854
// pulling frames from its internal buffers.
852855
continue;
853856
}
854-
UniqueAVPacket packet(av_packet_alloc());
857+
ReferenceAVPacket packet(autoAVPacket);
855858
ffmpegStatus = av_read_frame(formatContext_.get(), packet.get());
856859
decodeStats_.numPacketsRead++;
857860
if (ffmpegStatus == AVERROR_EOF) {
@@ -882,12 +885,12 @@ VideoDecoder::RawDecodedOutput VideoDecoder::getDecodedOutputWithFilter(
882885
}
883886
ffmpegStatus = avcodec_send_packet(
884887
streamInfos_[packet->stream_index].codecContext.get(), packet.get());
885-
decodeStats_.numPacketsSentToDecoder++;
886888
if (ffmpegStatus < AVSUCCESS) {
887889
throw std::runtime_error(
888890
"Could not push packet to decoder: " +
889891
getFFMPEGErrorStringFromErrorCode(ffmpegStatus));
890892
}
893+
decodeStats_.numPacketsSentToDecoder++;
891894
}
892895
if (ffmpegStatus < AVSUCCESS) {
893896
if (reachedEOF || ffmpegStatus == AVERROR_EOF) {

0 commit comments

Comments
 (0)