@@ -156,14 +156,34 @@ void Video::_getDecoderParams(
156156
157157} //  _get decoder params
158158
159- Video::Video (std::string videoPath, std::string stream, int64_t  numThreads) {
160-   C10_LOG_API_USAGE_ONCE (" torchvision.csrc.io.video.video.Video" 
159+ void  Video::initFromFile (
160+     std::string videoPath,
161+     std::string stream,
162+     int64_t  numThreads) {
163+   TORCH_CHECK (!initialized, " Video object can only be initialized once" 
164+   initialized = true ;
165+   params.uri  = videoPath;
166+   _init (stream, numThreads);
167+ }
168+ 
169+ void  Video::initFromMemory (
170+     torch::Tensor videoTensor,
171+     std::string stream,
172+     int64_t  numThreads) {
173+   TORCH_CHECK (!initialized, " Video object can only be initialized once" 
174+   initialized = true ;
175+   callback = MemoryBuffer::getCallback (
176+       videoTensor.data_ptr <uint8_t >(), videoTensor.size (0 ));
177+   _init (stream, numThreads);
178+ }
179+ 
180+ void  Video::_init (std::string stream, int64_t  numThreads) {
161181  //  set number of threads global
162182  numThreads_ = numThreads;
163183  //  parse stream information
164184  current_stream = _parseStream (stream);
165185  //  note that in the initial call we want to get all streams
166-   Video:: _getDecoderParams
186+   _getDecoderParams (
167187      0 , //  video start
168188      0 , //  headerOnly
169189      std::get<0 >(current_stream), //  stream info - remove that
@@ -175,11 +195,6 @@ Video::Video(std::string videoPath, std::string stream, int64_t numThreads) {
175195
176196  std::string logMessage, logType;
177197
178-   //  TODO: add read from memory option
179-   params.uri  = videoPath;
180-   logType = " file" 
181-   logMessage = videoPath;
182- 
183198  //  locals
184199  std::vector<double > audioFPS, videoFPS;
185200  std::vector<double > audioDuration, videoDuration, ccDuration, subsDuration;
@@ -190,7 +205,8 @@ Video::Video(std::string videoPath, std::string stream, int64_t numThreads) {
190205  c10::Dict<std::string, std::vector<double >> subsMetadata;
191206
192207  //  callback and metadata defined in struct
193-   succeeded = decoder.init (params, std::move (callback), &metadata);
208+   DecoderInCallback tmp_callback = callback;
209+   succeeded = decoder.init (params, std::move (tmp_callback), &metadata);
194210  if  (succeeded) {
195211    for  (const  auto & header : metadata) {
196212      double  fps = double (header.fps );
@@ -225,16 +241,24 @@ Video::Video(std::string videoPath, std::string stream, int64_t numThreads) {
225241  streamsMetadata.insert (" subtitles" 
226242  streamsMetadata.insert (" cc" 
227243
228-   succeeded = Video:: setCurrentStream
244+   succeeded = setCurrentStream (stream);
229245  LOG (INFO) << " \n Decoder inited with: " " \n " 
230246  if  (std::get<1 >(current_stream) != -1 ) {
231247    LOG (INFO)
232248        << " Stream index set to " 1 >(current_stream)
233249        << " . If you encounter trouble, consider switching it to automatic stream discovery. \n " 
234250  }
251+ }
252+ 
253+ Video::Video (std::string videoPath, std::string stream, int64_t  numThreads) {
254+   C10_LOG_API_USAGE_ONCE (" torchvision.csrc.io.video.video.Video" 
255+   if  (!videoPath.empty ()) {
256+     initFromFile (videoPath, stream, numThreads);
257+   }
235258} //  video
236259
237260bool  Video::setCurrentStream (std::string stream = " video" 
261+   TORCH_CHECK (initialized, " Video object has to be initialized first" 
238262  if  ((!stream.empty ()) && (_parseStream (stream) != current_stream)) {
239263    current_stream = _parseStream (stream);
240264  }
@@ -256,19 +280,23 @@ bool Video::setCurrentStream(std::string stream = "video") {
256280  );
257281
258282  //  callback and metadata defined in Video.h
259-   return  (decoder.init (params, std::move (callback), &metadata));
283+   DecoderInCallback tmp_callback = callback;
284+   return  (decoder.init (params, std::move (tmp_callback), &metadata));
260285}
261286
262287std::tuple<std::string, int64_t > Video::getCurrentStream () const  {
288+   TORCH_CHECK (initialized, " Video object has to be initialized first" 
263289  return  current_stream;
264290}
265291
266292c10::Dict<std::string, c10::Dict<std::string, std::vector<double >>> Video::
267293    getStreamMetadata () const  {
294+   TORCH_CHECK (initialized, " Video object has to be initialized first" 
268295  return  streamsMetadata;
269296}
270297
271298void  Video::Seek (double  ts, bool  fastSeek = false ) {
299+   TORCH_CHECK (initialized, " Video object has to be initialized first" 
272300  //  initialize the class variables used for seeking and retrurn
273301  _getDecoderParams (
274302      ts, //  video start
@@ -282,11 +310,14 @@ void Video::Seek(double ts, bool fastSeek = false) {
282310  );
283311
284312  //  callback and metadata defined in Video.h
285-   succeeded = decoder.init (params, std::move (callback), &metadata);
313+   DecoderInCallback tmp_callback = callback;
314+   succeeded = decoder.init (params, std::move (tmp_callback), &metadata);
315+ 
286316  LOG (INFO) << " Decoder init at seek " " \n " 
287317}
288318
289319std::tuple<torch::Tensor, double > Video::Next () {
320+   TORCH_CHECK (initialized, " Video object has to be initialized first" 
290321  //  if failing to decode simply return a null tensor (note, should we
291322  //  raise an exeption?)
292323  double  frame_pts_s;
@@ -345,6 +376,8 @@ std::tuple<torch::Tensor, double> Video::Next() {
345376static  auto  registerVideo =
346377    torch::class_<Video>(" torchvision" " Video" 
347378        .def(torch::init<std::string, std::string, int64_t >())
379+         .def(" init_from_file" 
380+         .def(" init_from_memory" 
348381        .def(" get_current_stream" 
349382        .def(" set_current_stream" 
350383        .def(" get_metadata" 
0 commit comments