Advertisement
Guest User

Untitled

a guest
Jan 6th, 2021
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.68 KB | None | 0 0
  1. /*
  2.  
  3. # Compile
  4. gcc avpacket_to_gst.c -o avpacket_to_gst `pkg-config --cflags --libs gstreamer-1.0 gstreamer-app-1.0` `pkg-config --cflags --libs libavcodec libavdevice libavfilter libavformat libavutil libswscale libswresample`
  5.  
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <string.h>
  10.  
  11. #include <gst/gst.h>
  12. #include <gst/app/gstappsrc.h>
  13. #include <gst/app/gstappsink.h>
  14. #include <glib.h>
  15.  
  16. #include <libavcodec/avcodec.h>
  17. #include <libavformat/avformat.h>
  18. #include <libswscale/swscale.h>
  19. #include <libavutil/imgutils.h>
  20.  
  21. /* For mp4 file - street_0.mp4 */
  22. // const gchar *video_caps = "video/x-h264, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, alignment=(string)au, stream-format=(string)avc";
  23. const gchar *video_caps = "video/x-h264, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, alignment=(string)au, stream-format=(string)byte-stream";
  24. // const gchar *video_caps = "video/x-h264, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, alignment=(string)nal, stream-format=(string)avc";
  25. // const gchar *video_caps = "video/x-h264, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, alignment=(string)nal, stream-format=(string)byte-stream";
  26.  
  27. /* For ogg file - street_0.ogg */
  28. // const gchar *video_caps = "video/x-theora, width=(int)1920, height=(int)1080, framerate=(fraction)30/1";
  29.  
  30.  
  31. typedef struct _AppSrcData
  32. {
  33.     GstElement *app_source;
  34.     gint appsrc_frame_num;
  35.     guint fps;
  36.     char *in_file_path;
  37.  
  38. } AppSrcData;
  39.  
  40. static inline guint64 gst_ffmpeg_time_ff_to_gst(gint64 pts, AVRational base)
  41. {
  42.     guint64 out;
  43.  
  44.     if (pts == AV_NOPTS_VALUE)
  45.     {
  46.         out = GST_CLOCK_TIME_NONE;
  47.     }
  48.     else
  49.     {
  50.         AVRational bq = {1, GST_SECOND};
  51.         out = av_rescale_q(pts, base, bq);
  52.     }
  53.  
  54.     return out;
  55. }
  56.  
  57. void *av_push_data(void *args)
  58. {
  59.     /* AppSrcData struct. */
  60.     AppSrcData *data = (AppSrcData *)args;
  61.  
  62.     /* Libav vars. */
  63.     AVFormatContext *pFormatCtx = NULL;
  64.     int i, videoStream;
  65.     AVCodecContext *pCodecCtx = NULL;
  66.     AVCodec *pCodec = NULL;
  67.     AVPacket packet;
  68.     AVDictionary *optionsDict = NULL;
  69.     AVStream *av_stream = NULL;
  70.  
  71.     GstBuffer *outbuf = NULL;
  72.     GstClockTime timestamp, duration, start_time;
  73.     gint outsize;
  74.     gint64 pts;
  75.     GstFlowReturn gstret;
  76.  
  77.     // Register all formats and codecs
  78.     av_register_all();
  79.  
  80.     // Open video file
  81.     if (avformat_open_input(&pFormatCtx, data->in_file_path, NULL, NULL) != 0)
  82.     {
  83.         g_printerr("Couldn't open file.\n");
  84.         return FALSE; // Couldn't open file
  85.     }
  86.  
  87.     // Retrieve stream information.
  88.     if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
  89.     {
  90.         g_printerr("Couldn't find stream information.\n");
  91.         return FALSE;
  92.     }
  93.  
  94.     // Dump information about file onto standard error.
  95.     av_dump_format(pFormatCtx, 0, data->in_file_path, 0);
  96.  
  97.     // Find the first video stream.
  98.     videoStream = -1;
  99.     for (i = 0; i < pFormatCtx->nb_streams; i++)
  100.     {
  101.         if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
  102.         {
  103.             videoStream = i;
  104.             break;
  105.         }
  106.     }
  107.  
  108.     if (videoStream == -1)
  109.     {
  110.         g_printerr("Didn't find a video stream.\n");
  111.         return FALSE;
  112.     }
  113.  
  114.     // Get video stream.
  115.     av_stream = pFormatCtx->streams[videoStream];
  116.  
  117.     // Get a pointer to the codec context for the video stream
  118.     pCodecCtx = pFormatCtx->streams[videoStream]->codec;
  119.  
  120.     // Find the decoder for the video stream
  121.     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
  122.     g_print("codec name: %s\n", pCodec->name);
  123.  
  124.     if (pCodec == NULL)
  125.     {
  126.         g_printerr("Unsupported codec.\n");
  127.         return FALSE;
  128.     }
  129.  
  130.     // Open codec
  131.     if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0)
  132.     {
  133.         g_printerr("Could not open codec.\n");
  134.         return FALSE;
  135.     }
  136.  
  137.     while (av_read_frame(pFormatCtx, &packet) >= 0)
  138.     {
  139.         // Is this a packet from the video stream?
  140.         if (packet.stream_index == videoStream)
  141.         {
  142.  
  143.             pts = packet.pts;
  144.             if (G_UNLIKELY(pts < 0))
  145.             {
  146.                 g_print("Warning: Packet contains negative pts. Pts is set to 0.\n");
  147.                 pts = 0;
  148.             }
  149.  
  150.             timestamp = gst_ffmpeg_time_ff_to_gst(pts, av_stream->time_base);
  151.             duration = gst_ffmpeg_time_ff_to_gst(packet.duration, av_stream->time_base);
  152.             if (G_UNLIKELY(!duration))
  153.             {
  154.                 g_print("Warning: duration is GST_CLOCK_TIME_NONE.\n");
  155.                 duration = GST_CLOCK_TIME_NONE;
  156.             }
  157.  
  158.             outsize = packet.size;
  159.             outbuf = gst_buffer_new_and_alloc(outsize);
  160.             gst_buffer_fill(outbuf, 0, packet.data, outsize);
  161.  
  162.             GST_BUFFER_TIMESTAMP(outbuf) = timestamp;
  163.             GST_BUFFER_DURATION(outbuf) = duration;
  164.             GST_BUFFER_PTS(outbuf) = gst_util_uint64_scale(data->appsrc_frame_num, GST_SECOND, data->fps);
  165.  
  166.             gstret = gst_app_src_push_buffer((GstAppSrc *)data->app_source, outbuf);
  167.             if (gstret != GST_FLOW_OK)
  168.             {
  169.                 g_print("Error: gst_app_src_push_buffer returned %d \n", gstret);
  170.                 return FALSE;
  171.             }
  172.             data->appsrc_frame_num++;
  173.         }
  174.  
  175.         // Free the packet that was allocated by av_read_frame
  176.         av_packet_unref(&packet);
  177.     }
  178.  
  179.     gstret = gst_app_src_end_of_stream((GstAppSrc *)data->app_source);
  180.     if (gstret != GST_FLOW_OK)
  181.     {
  182.         g_print("Error: gst_app_src_end_of_stream returned %d. EoS not queued successfully.\n", gstret);
  183.     }
  184.  
  185.     // Close the codec
  186.     avcodec_close(pCodecCtx);
  187.  
  188.     // Close the video file
  189.     avformat_close_input(&pFormatCtx);
  190.  
  191.     g_print(" << The av_thread is finished.\n");
  192.     return 0;
  193. }
  194.  
  195. static gboolean bus_call(GstBus *bus, GstMessage *message, gpointer data)
  196. {
  197.  
  198.     GMainLoop *loop = (GMainLoop *)data;
  199.     GError *err = NULL;
  200.     gchar *dbg_info = NULL;
  201.  
  202.     switch (GST_MESSAGE_TYPE(message))
  203.     {
  204.     case GST_MESSAGE_EOS:
  205.         g_print("Finished playback\n");
  206.         g_main_loop_quit(loop);
  207.         break;
  208.     case GST_MESSAGE_ERROR:
  209.         gst_message_parse_error(message, &err, &dbg_info);
  210.         g_printerr("ERROR from element %s: %s\n", GST_OBJECT_NAME(message->src), err->message);
  211.         g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
  212.         g_error_free(err);
  213.         g_free(dbg_info);
  214.         g_main_loop_quit(loop);
  215.         break;
  216.     default:
  217.         break;
  218.     }
  219.     return TRUE;
  220. }
  221.  
  222. int main(int argc, char *argv[])
  223. {
  224.     GMainLoop *loop = NULL;
  225.     GstElement *pipeline = NULL, *conv = NULL, *videosink = NULL, *decoder = NULL, *testsink = NULL;
  226.     GstBus *bus = NULL;
  227.  
  228.     guint bus_watch_id;
  229.     AppSrcData data;
  230.  
  231.     const int width = 1920;
  232.     const int height = 1080;
  233.     const int fps = 30;
  234.  
  235.     /* Check input arguments */
  236.     if (argc != 2)
  237.     {
  238.         g_printerr("Usage: %s <Raw filename> \n", argv[0]);
  239.         return -1;
  240.     }
  241.  
  242.     /* Initialize custom data structure */
  243.     memset(&data, 0, sizeof(data));
  244.  
  245.     data.fps = fps;
  246.     data.in_file_path = argv[1];
  247.  
  248.     /* Standard GStreamer initialization */
  249.     gst_init(&argc, &argv);
  250.     loop = g_main_loop_new(NULL, FALSE);
  251.  
  252.     /* Create gstreamer elements */
  253.     pipeline = gst_pipeline_new("av_packet_reading");
  254.     if (!pipeline)
  255.     {
  256.         g_printerr("Pipeline could not be created. Exiting.\n");
  257.         return -1;
  258.     }
  259.  
  260.     gchar *string = NULL;
  261.  
  262.     string = g_strdup_printf("appsrc name=app_source caps=\"%s\" ! decodebin ! videoconvert ! autovideosink", video_caps);
  263.     // string = g_strdup_printf("appsrc name=app_source caps=\"%s\" ! h264parse ! videoconvert ! autovideosink", video_caps);
  264.     // string = g_strdup_printf("appsrc name=app_source caps=\"%s\" ! theoradec ! videoconvert ! autovideosink", video_caps);
  265.  
  266.     pipeline = gst_parse_launch(string, NULL);
  267.     g_free(string);
  268.  
  269.     if (pipeline == NULL)
  270.     {
  271.         g_print("Bad sink\n");
  272.         return -1;
  273.     }
  274.  
  275.     data.app_source = gst_bin_get_by_name(GST_BIN(pipeline), "app_source");
  276.  
  277.     bus = gst_element_get_bus(pipeline);
  278.     gst_bus_add_watch(bus, (GstBusFunc)bus_call, loop);
  279.     gst_object_unref(bus);
  280.  
  281.     // Run a thread to read data a from file and to feed the appsrc element.
  282.     pthread_t thread_id;
  283.     pthread_create(&thread_id, NULL, av_push_data, &data);
  284.  
  285.     gst_element_set_state(pipeline, GST_STATE_PLAYING);
  286.  
  287.     /* Pipeline is running. */
  288.     g_main_loop_run(loop);
  289.  
  290.     gst_element_set_state(pipeline, GST_STATE_NULL);
  291.  
  292.     gst_object_unref(pipeline);
  293.     g_main_loop_unref(loop);
  294.  
  295.     // pthread_exit(NULL);
  296.     return 0;
  297. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement