diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 7519f040b..ab213947e 100755 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -624,14 +624,20 @@ SET(UT_FILES ) SET(SAMPLE_UT_FILES - test/utmain.cpp - test/test_utils.cpp - test/test_utils.h - .././samples/timelapse-sample/timelapse_summary_test.cpp + test/utmain.cpp + test/test_utils.cpp + test/test_utils.h + ../samples/create_thumbnail_from_mp4_video/test_generate_thumbnail_from_mp4_video.cpp + ../samples/play_mp4_from_beginning/test_play_mp4_video_from_beginning.cpp + .././samples/timelapse-sample/timelapse_summary_test.cpp ) SET(SAMPLE_CORE_FILES - ../samples/timelapse-sample/timelapse_summary.h + ../samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.h + ../samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.cpp + ../samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.h + ../samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.cpp + ../samples/timelapse-sample/timelapse_summary.h ../samples/timelapse-sample/timelapse_summary.cpp ) @@ -639,7 +645,6 @@ SET(SAMPLE_SOURCE ${SAMPLE_CORE_FILES} ${SAMPLE_UT_FILES} ) - IF(ENABLE_LINUX) list(APPEND UT_FILES test/gtkglrenderer_tests.cpp @@ -653,7 +658,6 @@ IF(ENABLE_LINUX) ENDIF(ENABLE_LINUX) add_executable(aprapipesut ${UT_FILES}) - add_executable(aprapipessampleut ${SAMPLE_SOURCE}) IF(ENABLE_ARM64) @@ -679,6 +683,17 @@ ${NVCODEC_INCLUDE_DIR} test ) +IF(ENABLE_ARM64) + target_include_directories ( aprapipesut PRIVATE ${JETSON_MULTIMEDIA_LIB_INCLUDE} ${FFMPEG_ROOT} ${JPEG_INCLUDE_DIR}) +ENDIF(ENABLE_ARM64) + +IF (ENABLE_CUDA) + target_include_directories ( aprapipesut PRIVATE ${NVCODEC_INCLUDE_DIR}) +ENDIF (ENABLE_CUDA) + + +find_library(OPENH264_LIB NAMES openh264.lib libopenh264.a REQUIRED) +find_library(LIBMP4_LIB NAMES mp4lib.lib libmp4lib.a REQUIRED) target_link_libraries(aprapipessampleut aprapipes diff --git a/base/src/Mp4ReaderSource.cpp b/base/src/Mp4ReaderSource.cpp index f2fd08136..1cfe133d4 100644 --- a/base/src/Mp4ReaderSource.cpp +++ b/base/src/Mp4ReaderSource.cpp @@ -629,20 +629,20 @@ class Mp4ReaderDetailAbs { int seekedToFrame = -1; uint64_t skipMsecsInFile = 0; - - if (!mState.startTimeStampFromFile) + + if (!mState.resolvedStartingTS) { LOG_ERROR << "Start timestamp is not saved in the file. Can't support seeking with timestamps."; return false; } - if (skipTS < mState.startTimeStampFromFile) + if (skipTS < mState.resolvedStartingTS) { LOG_INFO << "seek time outside range. Seeking to start of video."; skipMsecsInFile = 0; } else { - skipMsecsInFile = skipTS - mState.startTimeStampFromFile; + skipMsecsInFile = skipTS - mState.resolvedStartingTS; } LOG_INFO << "Attempting seek <" << mState.mVideoPath << "> @skipMsecsInFile <" << skipMsecsInFile << ">"; diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index a24ea02f7..a9ff6823f 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -4,4 +4,6 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) -add_subdirectory(timelapse-sample) \ No newline at end of file +add_subdirectory(create_thumbnail_from_mp4_video) +add_subdirectory(play_mp4_from_beginning) +add_subdirectory(timelapse-sample) diff --git a/samples/create_thumbnail_from_mp4_video/CMakeLists.txt b/samples/create_thumbnail_from_mp4_video/CMakeLists.txt new file mode 100644 index 000000000..f80673668 --- /dev/null +++ b/samples/create_thumbnail_from_mp4_video/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 3.22) +set(TARGET generateThumbnailFromMp4Video) +SET(SAMPLE_FILES + GenerateThumbnailsPipeline.cpp + pipelineMain.cpp +) +SET(SAMPLE_FILES_H + GenerateThumbnailsPipeline.h +) +SET(SOURCE + ${SAMPLE_FILES} + ${SAMPLE_FILES_H} +) +add_executable(${TARGET} ${SOURCE}) +target_include_directories ( ${TARGET} PRIVATE + ${JETSON_MULTIMEDIA_LIB_INCLUDE} + ${OpenCV_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${LIBMP4_INC_DIR} + ${NVCODEC_INCLUDE_DIR} +) +target_link_libraries( + ${TARGET} + aprapipes + ${JPEG_LIBRARIES} + ${LIBMP4_LIB} + ${OPENH264_LIB} + ${Boost_LIBRARIES} + ${FFMPEG_LIBRARIES} + ${OpenCV_LIBRARIES} + ${NVCUDAToolkit_LIBS} + ${NVCODEC_LIB} + ${NVJPEGLIB_L4T} + ) \ No newline at end of file diff --git a/samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.cpp b/samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.cpp new file mode 100644 index 000000000..16ffe45cb --- /dev/null +++ b/samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.cpp @@ -0,0 +1,89 @@ + +#include "GenerateThumbnailsPipeline.h" +#include "CudaMemCopy.h" +#include "ExternalSinkModule.h" +#include "FileReaderModule.h" +#include "FileWriterModule.h" +#include "FrameMetadata.h" +#include "H264Decoder.h" +#include "H264Metadata.h" +#include "JPEGEncoderNVJPEG.h" +#include "Logger.h" +#include "Mp4ReaderSource.h" +#include "Mp4VideoMetadata.h" +#include "ValveModule.h" +#include + +GenerateThumbnailsPipeline::GenerateThumbnailsPipeline() + : pipeLine("thumnailSamplePipeline") {} + +bool GenerateThumbnailsPipeline::setUpPipeLine( + const std::string &videoPath, const std::string &outFolderPath) { + // Implementation + + bool parseFS = false; + auto h264ImageMetadata = framemetadata_sp(new H264Metadata(0, 0)); + auto frameType = FrameMetadata::FrameType::H264_DATA; + auto mp4ReaderProps = + Mp4ReaderSourceProps(videoPath, parseFS, 0, true, false, false); + //initializing source Mp4 reader to read Mp4 video + mMp4Reader = + boost::shared_ptr(new Mp4ReaderSource(mp4ReaderProps)); + mMp4Reader->addOutPutPin(h264ImageMetadata); + + auto mp4Metadata = framemetadata_sp(new Mp4VideoMetadata("v_1")); + mMp4Reader->addOutPutPin(mp4Metadata); + + std::vector mImagePin; + mImagePin = mMp4Reader->getAllOutputPinsByType(frameType); + + //initializing H264 decoder to decode frame in H264 format + mDecoder = + boost::shared_ptr(new H264Decoder(H264DecoderProps())); + //Selecting an image pin of H264 data frame type is necessary because the decoder processes H264 frames for decoding. + mMp4Reader->setNext(mDecoder, mImagePin); + + //Initializing the valve to send only one frame. It is currently set to 0, meaning no frames are captured. + mValve = boost::shared_ptr(new ValveModule(ValveModuleProps(0))); + mDecoder->setNext(mValve); + + //initialize cuda memory + auto stream = cudastream_sp(new ApraCudaStream); + mCudaCopy = boost::shared_ptr( + new CudaMemCopy(CudaMemCopyProps(cudaMemcpyHostToDevice, stream))); + mValve->setNext(mCudaCopy); + + //initializing Jpeg encoder to encode the frame in jpeg format + mJpegEncoder = boost::shared_ptr( + new JPEGEncoderNVJPEG(JPEGEncoderNVJPEGProps(stream))); + mCudaCopy->setNext(mJpegEncoder); + + //initilizing file writer as sink to write frame at given path + mFileWriter = boost::shared_ptr( + new FileWriterModule(FileWriterModuleProps(outFolderPath))); + mJpegEncoder->setNext(mFileWriter); + + return true; +} + +bool GenerateThumbnailsPipeline::startPipeLine() { + pipeLine.appendModule(mMp4Reader); + if (!pipeLine.init()) { + throw AIPException( + AIP_FATAL, + "Engine Pipeline init failed. Check IPEngine Logs for more details."); + return false; + } + pipeLine.run_all_threaded(); + //allowing only one frame to get captured. + mValve->allowFrames(1); + + return true; +} + +bool GenerateThumbnailsPipeline::stopPipeLine() { + pipeLine.stop(); + pipeLine.term(); + pipeLine.wait_for_all(); + return true; +} diff --git a/samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.h b/samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.h new file mode 100644 index 000000000..b421c74f0 --- /dev/null +++ b/samples/create_thumbnail_from_mp4_video/GenerateThumbnailsPipeline.h @@ -0,0 +1,30 @@ +#include +#include +#include "Mp4ReaderSource.h" +#include "H264Decoder.h" +#include "ColorConversionXForm.h" +#include "CudaMemCopy.h" +#include "FileWriterModule.h" +#include "JPEGEncoderNVJPEG.h" + + + +class GenerateThumbnailsPipeline +{ +public: + GenerateThumbnailsPipeline(); + bool setUpPipeLine(const std::string &videoPath,const std::string &outFolderPath); + bool startPipeLine(); + bool stopPipeLine(); + +private: + PipeLine pipeLine; + boost::shared_ptr mValve; + boost::shared_ptr mMp4Reader; + boost::shared_ptr mDecoder; + boost::shared_ptr mColorchange; + boost::shared_ptr mCudaCopy; + boost::shared_ptr mJpegEncoder; + boost::shared_ptr mFileWriter; +}; + diff --git a/samples/create_thumbnail_from_mp4_video/pipelineMain.cpp b/samples/create_thumbnail_from_mp4_video/pipelineMain.cpp new file mode 100644 index 000000000..0b0d4f11b --- /dev/null +++ b/samples/create_thumbnail_from_mp4_video/pipelineMain.cpp @@ -0,0 +1,32 @@ +#include "GenerateThumbnailsPipeline.h" +#include +#include + +void main(int argc, char *argv[]) { + if (argc < 3) { + std::cerr << "Usage: " << argv[0] << " " + << std::endl; + } + + std::string videoPath = argv[argc - 2]; + std::string outFolderPath = argv[argc - 1]; + + GenerateThumbnailsPipeline thumbnailPipeline; + if (!thumbnailPipeline.setUpPipeLine(videoPath, outFolderPath)) { + std::cerr << "Failed to setup pipeline." << std::endl; + } + + if (!thumbnailPipeline.startPipeLine()) { + std::cerr << "Failed to start pipeline." << std::endl; + } + + // Wait for the pipeline to run for 10 seconds + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + + // Stop the pipeline + if (!thumbnailPipeline.stopPipeLine()) { + std::cerr << "Failed to stop pipeline." << std::endl; + } else { + std::cerr << "Saved Generated Thumbnail in <" << outFolderPath << ">"; + } +} \ No newline at end of file diff --git a/samples/create_thumbnail_from_mp4_video/test_generate_thumbnail_from_mp4_video.cpp b/samples/create_thumbnail_from_mp4_video/test_generate_thumbnail_from_mp4_video.cpp new file mode 100644 index 000000000..a4232aa65 --- /dev/null +++ b/samples/create_thumbnail_from_mp4_video/test_generate_thumbnail_from_mp4_video.cpp @@ -0,0 +1,31 @@ +#include "GenerateThumbnailsPipeline.h" +#include "test_utils.h" +#include +#include + +BOOST_AUTO_TEST_SUITE(generateThumbnails) + +BOOST_AUTO_TEST_CASE(generateThumbnails_from_mp4) { + auto generateThumbnailPipeline = + boost::shared_ptr( + new GenerateThumbnailsPipeline()); + std::string videoPath = "../../data/Mp4_videos/h264_video_metadata/20230514/0011/1686723796848.mp4"; + std::string outFolderPath = "data/generated_thumbnail/thumbnail_????.jpg"; + BOOST_CHECK_NO_THROW(generateThumbnailPipeline->setUpPipeLine(videoPath, outFolderPath)); + BOOST_CHECK_NO_THROW(generateThumbnailPipeline->startPipeLine()); + + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + + const uint8_t *pReadDataTest = nullptr; + unsigned int readDataSizeTest = 0U; + + BOOST_TEST(Test_Utils::readFile("data/test_thumbnail/sample_thumbnail.jpg", + pReadDataTest, readDataSizeTest)); + Test_Utils::saveOrCompare( + "data/generated_thumbnail/thumbnail_0000.jpg", pReadDataTest, + readDataSizeTest, 0); + + generateThumbnailPipeline->stopPipeLine(); +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/samples/play_mp4_from_beginning/CMakeLists.txt b/samples/play_mp4_from_beginning/CMakeLists.txt new file mode 100644 index 000000000..7d46995bc --- /dev/null +++ b/samples/play_mp4_from_beginning/CMakeLists.txt @@ -0,0 +1,33 @@ +cmake_minimum_required(VERSION 3.22) +set(TARGET play_mp4_from_beginning) +SET(SAMPLE_FILES + PlayMp4VideoFromBeginning.cpp + pipelineMain.cpp +) +SET(SAMPLE_FILES_H + PlayMp4VideoFromBeginning.h +) +SET(SOURCE + ${SAMPLE_FILES} + ${SAMPLE_FILES_H} +) +add_executable(${TARGET} ${SOURCE}) +target_include_directories ( ${TARGET} PRIVATE + ${OpenCV_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${LIBMP4_INC_DIR} +) +target_link_libraries( + ${TARGET} + aprapipes + ${JPEG_LIBRARIES} + ${LIBMP4_LIB} + ${OPENH264_LIB} + ${Boost_LIBRARIES} + ${OpenCV_LIBRARIES} + ${NVCUDAToolkit_LIBS} + ${NVJPEGLIB_L4T} + ${NVCODEC_LIB} + ${FFMPEG_LIBRARIES} + ) + \ No newline at end of file diff --git a/samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.cpp b/samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.cpp new file mode 100644 index 000000000..a3d9a0892 --- /dev/null +++ b/samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.cpp @@ -0,0 +1,87 @@ + +#include "PlayMp4VideoFromBeginning.h" +#include "ColorConversionXForm.h" +#include "CudaMemCopy.h" +#include "ExternalSinkModule.h" +#include "FileWriterModule.h" +#include "Frame.h" +#include "FrameContainerQueue.h" +#include "FrameMetadata.h" +#include "H264Decoder.h" +#include "H264Metadata.h" +#include "ImageViewerModule.h" +#include "JPEGEncoderNVJPEG.h" +#include "Mp4ReaderSource.h" +#include "Mp4VideoMetadata.h" +#include + +PlayMp4VideoFromBeginning::PlayMp4VideoFromBeginning() + : pipeLine("PlayMp4videoFromBeginingSamplePipline") {} + +bool PlayMp4VideoFromBeginning::setUpPipeLine(const std::string &videoPath) { + // Implementation + bool parseFS = false; + auto h264ImageMetadata = framemetadata_sp(new H264Metadata(0, 0)); + auto frameType = FrameMetadata::FrameType::H264_DATA; + auto mp4ReaderProps = + Mp4ReaderSourceProps(videoPath, parseFS, 0, true, true, false); + mp4ReaderProps.fps = 24; + // initializing source Mp4 reader to read Mp4 video + mMp4Reader = + boost::shared_ptr(new Mp4ReaderSource(mp4ReaderProps)); + mMp4Reader->addOutPutPin(h264ImageMetadata); + + auto mp4Metadata = framemetadata_sp(new Mp4VideoMetadata("v_1")); + mMp4Reader->addOutPutPin(mp4Metadata); + + std::vector mImagePin; + mImagePin = mMp4Reader->getAllOutputPinsByType(frameType); + + // initializing H264 decoder to decode frame in H264 format + mDecoder = boost::shared_ptr(new H264Decoder(H264DecoderProps())); + + // Selecting an image pin of H264 data frame type is necessary because the + // decoder processes H264 frames for decoding. + mMp4Reader->setNext(mDecoder, mImagePin); + + //initializing conversion type module to convert YUV420 frame to RGB + auto conversionType = + ColorConversionProps::ConversionType::YUV420PLANAR_TO_RGB; + auto metadata = framemetadata_sp(new RawImagePlanarMetadata( + 1280, 720, ImageMetadata::ImageType::YUV420, size_t(0), CV_8U)); + mColorchange = boost::shared_ptr( + new ColorConversion(ColorConversionProps(conversionType))); + mDecoder->setNext(mColorchange); + + //initializing imageViewer module as sink to show video on screen + mImageViewerSink = boost::shared_ptr( + new ImageViewerModule(ImageViewerModuleProps("imageview"))); + mColorchange->setNext(mImageViewerSink); + + return true; +} + +bool PlayMp4VideoFromBeginning::startPipeLine() { + pipeLine.appendModule(mMp4Reader); + if (!pipeLine.init()) { + throw AIPException( + AIP_FATAL, + "Engine Pipeline init failed. Check IPEngine Logs for more details."); + return false; + } + pipeLine.run_all_threaded(); + return true; +} + +bool PlayMp4VideoFromBeginning::stopPipeLine() { + pipeLine.stop(); + pipeLine.term(); + pipeLine.wait_for_all(); + return true; +} + +bool PlayMp4VideoFromBeginning::flushQueuesAndSeek() { + pipeLine.flushAllQueues(); + mMp4Reader->randomSeek(1686723796848, false); + return true; +} diff --git a/samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.h b/samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.h new file mode 100644 index 000000000..d489e752c --- /dev/null +++ b/samples/play_mp4_from_beginning/PlayMp4VideoFromBeginning.h @@ -0,0 +1,24 @@ +#include "ColorConversionXForm.h" +#include "H264Decoder.h" +#include "ImageViewerModule.h" +#include "Mp4ReaderSource.h" + +#include + +class PlayMp4VideoFromBeginning { +public: + PlayMp4VideoFromBeginning(); + bool setUpPipeLine(const std::string &videoPath); + bool startPipeLine(); + bool stopPipeLine(); + bool flushQueuesAndSeek(); + + + boost::shared_ptr mMp4Reader; + boost::shared_ptr mImageViewerSink; + boost::shared_ptr mDecoder; + boost::shared_ptr mColorchange; + +private: + PipeLine pipeLine; +}; \ No newline at end of file diff --git a/samples/play_mp4_from_beginning/pipelineMain.cpp b/samples/play_mp4_from_beginning/pipelineMain.cpp new file mode 100644 index 000000000..3274cf83e --- /dev/null +++ b/samples/play_mp4_from_beginning/pipelineMain.cpp @@ -0,0 +1,30 @@ +#include "PlayMp4VideoFromBeginning.h" +#include +#include + +void main(int argc, char *argv[]) { + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " " + << std::endl; + } + std::string videoPath = argv[argc - 1]; + + PlayMp4VideoFromBeginning pipelineInstance; + + if (!pipelineInstance.setUpPipeLine(videoPath)) { + std::cerr << "Failed to setup pipeline." << std::endl; + } + if (!pipelineInstance.startPipeLine()) { + std::cerr << "Failed to start pipeline." << std::endl; + } + // Wait for the pipeline to run for 10 seconds + boost::this_thread::sleep_for(boost::chrono::seconds(3)); + if (!pipelineInstance.flushQueuesAndSeek()) { + std::cerr << "Failed to flush Queues." << std::endl; + } + boost::this_thread::sleep_for(boost::chrono::seconds(5)); + // Stop the pipeline + if (!pipelineInstance.stopPipeLine()) { + std::cerr << "Failed to stop pipeline." << std::endl; + } +} \ No newline at end of file diff --git a/samples/play_mp4_from_beginning/test_play_mp4_video_from_beginning.cpp b/samples/play_mp4_from_beginning/test_play_mp4_video_from_beginning.cpp new file mode 100644 index 000000000..e3e170a23 --- /dev/null +++ b/samples/play_mp4_from_beginning/test_play_mp4_video_from_beginning.cpp @@ -0,0 +1,87 @@ +#include "Frame.h" +#include "FrameContainerQueue.h" +#include "PlayMp4VideoFromBeginning.h" +#include "test_utils.h" +#include + +BOOST_AUTO_TEST_SUITE(start_video_from_beginning) +class SinkModuleProps : public ModuleProps { +public: + SinkModuleProps() : ModuleProps(){}; +}; + +class SinkModule : public Module { +public: + SinkModule(SinkModuleProps props) : Module(SINK, "sinkModule", props){}; + boost::shared_ptr getQue() { return Module::getQue(); } + frame_container pop() { return Module::pop(); } + +protected: + bool process() { return false; } + bool validateOutputPins() { return true; } + bool validateInputPins() { return true; } +}; + +BOOST_AUTO_TEST_CASE(play_mp4_from_beginning_flush_queue_test) { + auto playMp4VideoFromBeginning = boost::shared_ptr( + new PlayMp4VideoFromBeginning()); + std::string videoPath = "C:/APRA/fork/ApraPipes/data/Mp4_videos/" + "h264_video_metadata/20230514/0011/1686723796848.mp4"; + playMp4VideoFromBeginning->setUpPipeLine(videoPath); + + auto sink = boost::shared_ptr(new SinkModule(SinkModuleProps())); + playMp4VideoFromBeginning->mColorchange->setNext(sink); + BOOST_CHECK(playMp4VideoFromBeginning->mMp4Reader->init()); + BOOST_CHECK(playMp4VideoFromBeginning->mDecoder->init()); + BOOST_CHECK(playMp4VideoFromBeginning->mColorchange->init()); + BOOST_CHECK(sink->init()); + + for (int i = 0; i <= 20; i++) { + playMp4VideoFromBeginning->mMp4Reader->step(); + playMp4VideoFromBeginning->mDecoder->step(); + } + playMp4VideoFromBeginning->mColorchange->step(); + + auto frames = sink->pop(); + auto frame = frames.size(); + auto sinkQue = sink->getQue(); + BOOST_CHECK_EQUAL(frames.size(), 1); + sinkQue->flush(); + BOOST_CHECK_EQUAL(sinkQue->size(), 0); + frame_sp outputFrame = frames.cbegin()->second; + Test_Utils::saveOrCompare( + "./data/mp4Reader_saveOrCompare/h264/testplay.raw", + const_cast(static_cast(outputFrame->data())), + outputFrame->size(), 0); +} + +BOOST_AUTO_TEST_CASE(play_mp4_from_beginning_seek_test) { + auto playMp4VideoFromBeginning = boost::shared_ptr( + new PlayMp4VideoFromBeginning()); + std::string videoPath = "C:/APRA/fork/ApraPipes/data/Mp4_videos/" + "h264_video_metadata/20230514/0011/1686723796848.mp4"; + playMp4VideoFromBeginning->setUpPipeLine(videoPath); + auto sink = boost::shared_ptr(new SinkModule(SinkModuleProps())); + playMp4VideoFromBeginning->mMp4Reader->setNext(sink); + + BOOST_CHECK(playMp4VideoFromBeginning->mMp4Reader->init()); + BOOST_CHECK(playMp4VideoFromBeginning->mDecoder->init()); + BOOST_CHECK(playMp4VideoFromBeginning->mColorchange->init()); + BOOST_CHECK(sink->init()); + + playMp4VideoFromBeginning->mMp4Reader->step(); + + auto frames = sink->pop(); + auto imgFrame = frames.begin()->second; + + uint64_t skipTS = 1686723796848; + playMp4VideoFromBeginning->mMp4Reader->randomSeek(skipTS, false); + playMp4VideoFromBeginning->mMp4Reader->step(); + frames = sink->pop(); + imgFrame = frames.begin()->second; + BOOST_TEST(imgFrame->timestamp == 1686723796848); + LOG_INFO << "Found next available frame " << imgFrame->timestamp - skipTS + << " msecs later from skipTS"; +} + +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file