[JAVA-1166] Unable to read portion or time frame of video file from GridFS Created: 14/Apr/14  Updated: 11/Sep/19  Resolved: 16/Apr/14

Status: Closed
Project: Java Driver
Component/s: API
Affects Version/s: 2.4
Fix Version/s: None

Type: Task Priority: Major - P3
Reporter: Mahesh Ramichetty Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

OS: Windows 7
I7 processor 64bit
16GB ram
500GB harddisk



 Description   

We are able to save video file into GridFS and able to read complete video file from GridFS. But our requirement is to get certain time frame of the video file. Which we are unable to do it with existing mongoDB java Api.
Please let use know how to get the certain slice of the video from the GridFS. This requirement is for one of the government project in which we have to capture the video from footage's and save it to mongoDB. and retrieve the certain time-frame of the video on required basis, the footage that needs to be saved will come from 500+ digital cameras. this data has to be archived for 5 years(We have arrived at design from archiving stand point). This is marked as a blocker as we are not able to proceed with our POC.

Below is the code we have written to get video file from GridFS. Please share us with example of how to get certain time frame of video from GridFS using Java Api.

              OutputStream out = new FileOutputStream( new File("C:\\Users\\Administrator\\Pictures\\walkMongo.mp4") );
              Mongo mongo = new MongoClient("localhost", 27017);
              DB db = mongo.getDB("test");
              String newFileName = "walk";
              GridFS gfsPhoto = new GridFS(db,"video");
              GridFSDBFile imageForOutput = gfsPhoto.findOne(newFileName);
              DBCollection chunks = db.getCollection("video.chunks");
              BasicDBObject query =  new BasicDBObject();
              //DBCursor cur = chunks.find(query.append("files_id", imageForOutput.getId()).append("n", new BasicDBObject("$lt",10)));
              DBCursor cur = chunks.find(query.append("files_id", imageForOutput.getId()));
              System.out.println(cur.size());
              for (DBObject dbObject : cur) {
                     out.write((byte[])dbObject.get("data"));
              }
              imageForOutput.writeTo(out);



 Comments   
Comment by Mahesh Ramichetty [ 16/Apr/14 ]

Thanks Stephen and Jeff for the clarifications, we have also decided the approach that you have mentioned.but we are facing the issue in the retrieving of the video ,based on the approach this will be correct way to come up with the solution or not. Will post the same question in Stack overflow and other forums.

Comment by Stennie Steneker (Inactive) [ 16/Apr/14 ]

Hi Mahesh,

To be clear, reading and writing the contents of a video file format (eg. MP4) requires knowledge of the format and is outside the scope of the MongoDB Java driver.

In order to start video playback at a specific time offset, you need to first work out how you would do that with a video file on your local file system. I expect that would involve a library that understands the video file format, as there normally isn't a direct correlation between time and bytes. Once you determine the file offset, you should then be start retrieving chunks from GridFS at the specified offset using the InputStream.skip() method that Jeff mentioned.

This is definitely a more appropriate question for a programming forum like StackOverflow or perhaps even one of communities more specifically dedicated to working with video codecs.

Thanks,
Stephen

Comment by Mahesh Ramichetty [ 15/Apr/14 ]

Hi Jeff,

We are not using RandomAccessFile. below is the code which we have used to save and retrieve the video file from MongoDB gridFS. Could you please suggest how to retrieve the particular time frame of the video using GridFs.

    public static void saveAndReadVideo() throws Exception
    {
              Mongo mongo = new MongoClient("localhost", 27017);
              DB db = mongo.getDB("test");
              String newFileName = "walk";
              GridFS gfsPhoto = new GridFS(db,"video");
              File imageFile = new File("C:\\Users\\Administrator\\Pictures\\walk.mp4");
              
              //Saving vidoe file to gridFs
              GridFSInputFile gridFSInputFile = gfsPhoto.createFile(imageFile);
              gridFSInputFile.setFilename(newFileName);
              gridFSInputFile.save();
              
              //Retrieving video file from gridFS Files
              File imageFileMo = new File("C:\\Users\\Administrator\\Pictures\\walkFile.mp4");
              GridFSDBFile imageForOutput = gfsPhoto.findOne(newFileName);
              imageForOutput.writeTo(imageFileMo);
              
              //Retrieving video file from gridFS Chunks
              OutputStream out = new FileOutputStream( new File("C:\\Users\\Administrator\\Pictures\\walkChunk.mp4") );
              DBCollection chunks = db.getCollection("video.chunks");
              BasicDBObject query =  new BasicDBObject();
              DBCursor cur = chunks.find(query.append("files_id", imageForOutput.getId()));
              System.out.println(cur.size());
              for (DBObject dbObject : cur) {
                     out.write((byte[])dbObject.get("data"));
              }
              out.close();
    }

Comment by Mahesh Ramichetty [ 15/Apr/14 ]

Will be providing the code right away.............

Comment by Jeffrey Yemin [ 14/Apr/14 ]

Mahesh,

You misunderstood what I asked for. I'd like to see working code using FileInputStream or RandomAccessFile. Then we can figure out how to translate that code to GridFS.

Comment by Mahesh Ramichetty [ 14/Apr/14 ]

Thanks Jeff for responding back, The code for accessing the video is given above when we have raised this as a Question. Pls let us know if any other details are required.

Comment by Jeffrey Yemin [ 14/Apr/14 ]

Hi Mahesh,

It sounds like you are asking us to figure out how to translate a moment of time in the video file to a byte offset in that file. I don't see how we can do that without knowing the particulars of that video format. Perhaps you can help by sharing some code of how you would accomplish this task for a video file that was sitting on a hard drive, i.e by using either java.io.FileInputStream or java.io.RandomAccessFile. If you can do that, I'm sure we can figure out how to accomplish the same with GridFS.

I'd also like to point out that, since this is not really an issue with the Java driver itself, but rather with your application, a better forum would be either StackOverflow (tag the question with mongodb-java) or on the mongodb-user Google group. If we can determine that the Java driver has a bug or requires a new feature to accomplish your goal, then an issue can be opened here to track it.

Regards,
Jeff

Comment by Mahesh Ramichetty [ 14/Apr/14 ]

Jeff,

We had looked at the code that is in the Git hub, but that is not the code that retrofits the solution that we are looking for.

Let me explain what we are looking for.

1: Need to retrieve the video Footage (Portion) that is saved in to Mongo DB using GridFS based on the time frame.

2: we cannot determine the number of chunks that needs to be skipped to retrieve the correct footage.( Because the retrival is purely based on the time)

3: Pls provide a solution for the above scenario.

Comment by Mahesh Ramichetty [ 14/Apr/14 ]

Thanks for quick turn around Jeff, will keep you posted on the same once we test the code in the git hub link that is provided,basically we are trying to retrieve the video footage based on the time in that case how to determine that these many number chunks has to be skipped. The Skipping part plays a critical role in getting and displaying the right footage. Give us some time we will revert back on this.

Comment by Jeffrey Yemin [ 14/Apr/14 ]

Hi Mahesh,

How does your application determine what byte range of the file is needed? Does it use some information encoded at the beginning of the file?

That said, the driver does have support for the standard InputStream.skip(int bytesToSkip) method, which you can see usage of in this test: https://github.com/mongodb/mongo-java-driver/blob/master/src/test/com/mongodb/gridfs/GridFSTest.java#L185

Can you take a look at it and let us know if it meets your needs?

Comment by Mahesh Ramichetty [ 14/Apr/14 ]

Pls read the JAVA-1166 issue as GridFS, there was a typo mistake from our side.

Generated at Thu Feb 08 08:53:56 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.