<jupyter_start><jupyter_text>4.0  Video File OutputIt may be desirable to save an annotated file for later playback and analysis. Just as there are pipeline elements that decode and parse a file read from `filesrc` into a stream, the pattern can be reversed to save a video to file using `filesink`.  In this notebook, you'll learn how to add the elements required to encode, parse, multiplex, and save a video to file.  4.1 **[Build a Pipeline that Outputs to a File](04_overview)**&nbsp; &nbsp; &nbsp; 4.1.1 [Practice Application `deepstream-test3-mp4_out`](04_test3)&nbsp; &nbsp; &nbsp; 4.1.2 [Exercise: Build and Run the Base Application](04_ex_base)4.2 **[Create an Annotated Video File](04_elements)**&nbsp; &nbsp; &nbsp; 4.2.1 [Exercise: Output Annotated Video to File](04_ex_change)4.3 **[Put It All Together](04_final)**&nbsp; &nbsp; &nbsp; 4.3.1 [Exercise: Change the File Type](04_ex_challenge)  4.1 Build a Pipeline that Outputs to a FileIn all of the RTSP output apps used so far in this course, the pipeline ended with the following sequence of plugin elements:- `Gst-nvv4l2h264enc` - encodes RAW data in I420 format to H264- `GstRtpH264Pay` - converts H264 encoded Payload to RTP packets (RFC 3984)- `GstUDPSink` - sends UDP packets to the network. When paired with RTP payloader (`Gst-rtph264pay`) it can implement RTP streamingTo save a video stream to a file, we still need the H264 encoding plugin, `Gst-nvv4l2h264enc`, but not the `GstRtp264Pay` plugin for RTSP, nor the `GstUDPSink` since the stream won't be transmitted over the network.  Instead, we need to **parse** the encoded stream and **multiplex (aka "mux")** it into a convenient container, such as a QuickTime `.mp4` file.  The `filesink` element will will become the sink.In summary, saving our rendered streams to file requires the pipeline after rendering to be:- `Gst-nvv4l2h264enc` - encodes RAW data in I420 format to H264- `GstH264Parse` - parses the encoded H264 stream- `GstQTMux` -  merges streams (audio and video) into QuickTime(.mov) files- `GstFileSink` - writes incoming data to a file in the local file system  4.1.1 Practice Application `deepstream-test3-mp4_out`A comparison of the `deepstream-test3-rstp_out` C code and the C code for an equivalent application that writes to file, `deepstream-test-mp4_out`,  reveals the following differences *(Note: the sample snippets below are abbreviated code for clarity purposes)*:RTSP streaming [deepstream-test3-rstp_out](../deepstream_sdk_v4.0.2_jetson/sources/apps/dli_apps/deepstream-test3-rtsp_out/deepstream_test3_app.c) code:```c...  GstElement *pipeline = NULL, *streammux = NULL, *sink = NULL, *pgie = NULL,      *nvvidconv = NULL, *nvosd = NULL, *tiler = NULL, *encoder = NULL,       *rtppay = NULL, *transform = NULL, *cap_filter = NULL;...  encoder = gst_element_factory_make ("nvv4l2h264enc", "h264-encoder");  rtppay = gst_element_factory_make ("rtph264pay", "rtppay-h264");  g_object_set (G_OBJECT (encoder), "bitrate", 4000000, NULL);ifdef PLATFORM_TEGRA  g_object_set (G_OBJECT (encoder), "preset-level", 1, NULL);  g_object_set (G_OBJECT (encoder), "insert-sps-pps", 1, NULL);  g_object_set (G_OBJECT (encoder), "bufapi-version", 1, NULL);endif  sink = gst_element_factory_make ("udpsink", "udpsink");  g_object_set (G_OBJECT (sink), "host", "192.168.127.12", "port",      5400, "async", FALSE, "sync", 0, NULL);...      /* Set up the pipeline */  /* we add all elements into the pipeline */  gst_bin_add_many (GST_BIN (pipeline), pgie, tiler, nvvidconv, nvosd,      transform, cap_filter, encoder, rtppay, sink, NULL);  /* we link the elements together   * nvstreammux -> nvinfer -> nvtiler -> nvvidconv -> nvosd -> video-renderer */  if (!gst_element_link_many (streammux, pgie, tiler, nvvidconv, nvosd,          transform, cap_filter, encoder, rtppay, sink, NULL)) {    g_printerr ("Elements could not be linked. Exiting.\n");    return -1;  }...```File output [deepstream-test3-mp4_out](../deepstream_sdk_v4.0.2_jetson/sources/apps/dli_apps/deepstream-test3-mp4_out/deepstream_test3_app.c) code:```c...      GstElement *pipeline = NULL, *streammux = NULL, *sink = NULL, *pgie = NULL,      *nvvidconv = NULL, *nvosd = NULL, *tiler = NULL, *encoder = NULL,       *codecparse = NULL, *mux = NULL, *transform = NULL, *cap_filter = NULL;...      encoder = gst_element_factory_make ("nvv4l2h264enc", "h264-encoder");  //encoder = gst_element_factory_make ("avenc_mpeg4", "h264-encoder");  codecparse = gst_element_factory_make ("h264parse", "h264-parser");  //codecparse = gst_element_factory_make ("mpeg4videoparse", "mpeg4-parser");  mux = gst_element_factory_make ("qtmux", "mux");  sink = gst_element_factory_make ("filesink", "filesink");  g_object_set (G_OBJECT (sink), "location", "/home/dlinano/out.mp4", NULL);  g_object_set (G_OBJECT (encoder), "bitrate", 4000000, NULL);  g_object_set (G_OBJECT (encoder), "bufapi-version", 1, NULL);...      /* Set up the pipeline */  /* we add all elements into the pipeline */  gst_bin_add_many (GST_BIN (pipeline), pgie, tiler, nvvidconv, nvosd,      transform, cap_filter, encoder, codecparse, mux, sink, NULL);  /* we link the elements together   * nvstreammux -> nvinfer -> nvtiler -> nvvidconv -> nvosd -> video-renderer */  if (!gst_element_link_many (streammux, pgie, tiler, nvvidconv, nvosd,          transform, cap_filter, encoder, codecparse, mux, sink, NULL)) {    g_printerr ("Elements could not be linked. Exiting.\n");    return -1;  }...```Note the basic differences:* `rtppay` has been removed (`rtph264pay` element) * `codecparse` and `mux` has been added (`h264parse` and `qtmux` elements)* `sink` has been changed (from a `udspsink` element to a `filesink` element)   * no `host` property is needed   * `location` property is set for `filesink`  4.1.2 Exercise: Build and Run the Base ApplicationExecute the following cells to build the sample app.  DeepStream will save the result to `/home/dlinano/out.mp4` on the Jetson Nano.Download `out.mp4` by right clicking it in the JupyterLab file browser, then selecting "Download". Now play it on your machine.<jupyter_code># Build the test3 mp4 file output app
%cd /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps/dli_apps/deepstream-test3-mp4_out/
!make clean
!make
# Run the app
%cd /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps/dli_apps/deepstream-test3-mp4_out/
!./deepstream-test3-app \
file:///home/dlinano/deepstream_sdk_v4.0.2_jetson/samples/streams/sample_720p.h264 \
file:///home/dlinano/deepstream_sdk_v4.0.2_jetson/samples/streams/sample_720p.mp4<jupyter_output><empty_output><jupyter_text>4.2 Create an Annotated Video FileSince all of the RSTP samples you've worked with so far include the same elements after rendering, you'll be able to modify any of them to output to file in the same way as `deepstream-test3-mp4_out`.  4.2.1 Exercise: Output Annotated Video to FileCreate a new app based on `deepstream-test1-rtsp_out` that saves the annotated output to a file at `/home/dlinano/my_test1_out.mp4`<jupyter_code># Create a new app located at /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps/
#      my_apps/dst4-test1-filesink
#      based on deepstream-test1-rstp_out
%cd /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps
!mkdir -p my_apps/dst4-test1-filesink
!cp -rfv dli_apps/deepstream-test1-rtsp_out/* my_apps/dst4-test1-filesink<jupyter_output><empty_output><jupyter_text>Modify the [deepstream_test1_app.c](../deepstream_sdk_v4.0.2_jetson/sources/apps/my_apps/dst4-test1-filesink/deepstream_test1_app.c) with the following steps (refer to the code differences highlighted in the previous section for details):1. Declare `codecparse` and `mux` as GstElement objects2. Remove the `rtph264pay` element.3. Add `h264parse` and `qtmux` elements (assigned to `codecparse` and `mux`).4. Change `sink` from a `udspsink` element to a `filesink` element.   - Remove the "host" property that is no longer applicable.   - Set the "location" property.5. Change the `gst_bin_add_many()` and `gst_element_link_many()` methods so that the correct elements are included and linked.<jupyter_code># Build the app
%cd /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps/my_apps/dst4-test1-filesink
!make clean
!make
# Run the app
%cd /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps/my_apps/dst4-test1-filesink
!./deepstream-test1-app /home/dlinano/deepstream_sdk_v4.0.2_jetson/samples/streams/sample_720p.h264<jupyter_output><empty_output><jupyter_text>How did you do?If you see something like this image when you play your saved file, you did it!  If not, keep trying, or take a peek at the solution code in the solutions directory.     4.3 Put It All TogetherTry it again with a few small enhancements, starting with the recommended app below, or one of your own from earlier in the course.    4.3.1 Exercise: Change the File TypeAdd the following enhancements:* Remove the unnecessary call to the RTSP streamer* Save to a different file type such as `.avi` using the `avimux` element.* Provide the saved filename as a command line argument<jupyter_code># Create a new app located at /home/dlinano/deepstream_sdk_v4.0.2_jetson/sources/apps/
#      my_apps/dst4-test2-filesink
#      based on the original reference app deepstream-test2-rtsp_out
# TODO
# Add the encoder, parser, mux, and filesink to the C code
# Build the app
# TODO
# Run the app<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11133581692389569, 'fraction_numerical': 0.03161255987227249, 'mean_word_length': 4.810760667903525, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 1, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '383156', 'license': 'MIT', 'n_tokens_mistral': 3287, 'n_tokens_neox': 3123, 'n_words': 1021, 'path': '04_VideoFileOutput.ipynb', 'repo_name': 'RichardoMrMu/code-with-jetson-nano', 'size': '9396'}