Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- # Compile
- 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`
- */
- #include <stdio.h>
- #include <string.h>
- #include <gst/gst.h>
- #include <gst/app/gstappsrc.h>
- #include <gst/app/gstappsink.h>
- #include <glib.h>
- #include <libavcodec/avcodec.h>
- #include <libavformat/avformat.h>
- #include <libswscale/swscale.h>
- #include <libavutil/imgutils.h>
- /* For mp4 file - street_0.mp4 */
- // const gchar *video_caps = "video/x-h264, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, alignment=(string)au, stream-format=(string)avc";
- 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";
- // const gchar *video_caps = "video/x-h264, width=(int)1920, height=(int)1080, framerate=(fraction)30/1, alignment=(string)nal, stream-format=(string)avc";
- // 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";
- /* For ogg file - street_0.ogg */
- // const gchar *video_caps = "video/x-theora, width=(int)1920, height=(int)1080, framerate=(fraction)30/1";
- typedef struct _AppSrcData
- {
- GstElement *app_source;
- gint appsrc_frame_num;
- guint fps;
- char *in_file_path;
- } AppSrcData;
- static inline guint64 gst_ffmpeg_time_ff_to_gst(gint64 pts, AVRational base)
- {
- guint64 out;
- if (pts == AV_NOPTS_VALUE)
- {
- out = GST_CLOCK_TIME_NONE;
- }
- else
- {
- AVRational bq = {1, GST_SECOND};
- out = av_rescale_q(pts, base, bq);
- }
- return out;
- }
- void *av_push_data(void *args)
- {
- /* AppSrcData struct. */
- AppSrcData *data = (AppSrcData *)args;
- /* Libav vars. */
- AVFormatContext *pFormatCtx = NULL;
- int i, videoStream;
- AVCodecContext *pCodecCtx = NULL;
- AVCodec *pCodec = NULL;
- AVPacket packet;
- AVDictionary *optionsDict = NULL;
- AVStream *av_stream = NULL;
- GstBuffer *outbuf = NULL;
- GstClockTime timestamp, duration, start_time;
- gint outsize;
- gint64 pts;
- GstFlowReturn gstret;
- // Register all formats and codecs
- av_register_all();
- // Open video file
- if (avformat_open_input(&pFormatCtx, data->in_file_path, NULL, NULL) != 0)
- {
- g_printerr("Couldn't open file.\n");
- return FALSE; // Couldn't open file
- }
- // Retrieve stream information.
- if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
- {
- g_printerr("Couldn't find stream information.\n");
- return FALSE;
- }
- // Dump information about file onto standard error.
- av_dump_format(pFormatCtx, 0, data->in_file_path, 0);
- // Find the first video stream.
- videoStream = -1;
- for (i = 0; i < pFormatCtx->nb_streams; i++)
- {
- if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
- {
- videoStream = i;
- break;
- }
- }
- if (videoStream == -1)
- {
- g_printerr("Didn't find a video stream.\n");
- return FALSE;
- }
- // Get video stream.
- av_stream = pFormatCtx->streams[videoStream];
- // Get a pointer to the codec context for the video stream
- pCodecCtx = pFormatCtx->streams[videoStream]->codec;
- // Find the decoder for the video stream
- pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
- g_print("codec name: %s\n", pCodec->name);
- if (pCodec == NULL)
- {
- g_printerr("Unsupported codec.\n");
- return FALSE;
- }
- // Open codec
- if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0)
- {
- g_printerr("Could not open codec.\n");
- return FALSE;
- }
- while (av_read_frame(pFormatCtx, &packet) >= 0)
- {
- // Is this a packet from the video stream?
- if (packet.stream_index == videoStream)
- {
- pts = packet.pts;
- if (G_UNLIKELY(pts < 0))
- {
- g_print("Warning: Packet contains negative pts. Pts is set to 0.\n");
- pts = 0;
- }
- timestamp = gst_ffmpeg_time_ff_to_gst(pts, av_stream->time_base);
- duration = gst_ffmpeg_time_ff_to_gst(packet.duration, av_stream->time_base);
- if (G_UNLIKELY(!duration))
- {
- g_print("Warning: duration is GST_CLOCK_TIME_NONE.\n");
- duration = GST_CLOCK_TIME_NONE;
- }
- outsize = packet.size;
- outbuf = gst_buffer_new_and_alloc(outsize);
- gst_buffer_fill(outbuf, 0, packet.data, outsize);
- GST_BUFFER_TIMESTAMP(outbuf) = timestamp;
- GST_BUFFER_DURATION(outbuf) = duration;
- GST_BUFFER_PTS(outbuf) = gst_util_uint64_scale(data->appsrc_frame_num, GST_SECOND, data->fps);
- gstret = gst_app_src_push_buffer((GstAppSrc *)data->app_source, outbuf);
- if (gstret != GST_FLOW_OK)
- {
- g_print("Error: gst_app_src_push_buffer returned %d \n", gstret);
- return FALSE;
- }
- data->appsrc_frame_num++;
- }
- // Free the packet that was allocated by av_read_frame
- av_packet_unref(&packet);
- }
- gstret = gst_app_src_end_of_stream((GstAppSrc *)data->app_source);
- if (gstret != GST_FLOW_OK)
- {
- g_print("Error: gst_app_src_end_of_stream returned %d. EoS not queued successfully.\n", gstret);
- }
- // Close the codec
- avcodec_close(pCodecCtx);
- // Close the video file
- avformat_close_input(&pFormatCtx);
- g_print(" << The av_thread is finished.\n");
- return 0;
- }
- static gboolean bus_call(GstBus *bus, GstMessage *message, gpointer data)
- {
- GMainLoop *loop = (GMainLoop *)data;
- GError *err = NULL;
- gchar *dbg_info = NULL;
- switch (GST_MESSAGE_TYPE(message))
- {
- case GST_MESSAGE_EOS:
- g_print("Finished playback\n");
- g_main_loop_quit(loop);
- break;
- case GST_MESSAGE_ERROR:
- gst_message_parse_error(message, &err, &dbg_info);
- g_printerr("ERROR from element %s: %s\n", GST_OBJECT_NAME(message->src), err->message);
- g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
- g_error_free(err);
- g_free(dbg_info);
- g_main_loop_quit(loop);
- break;
- default:
- break;
- }
- return TRUE;
- }
- int main(int argc, char *argv[])
- {
- GMainLoop *loop = NULL;
- GstElement *pipeline = NULL, *conv = NULL, *videosink = NULL, *decoder = NULL, *testsink = NULL;
- GstBus *bus = NULL;
- guint bus_watch_id;
- AppSrcData data;
- const int width = 1920;
- const int height = 1080;
- const int fps = 30;
- /* Check input arguments */
- if (argc != 2)
- {
- g_printerr("Usage: %s <Raw filename> \n", argv[0]);
- return -1;
- }
- /* Initialize custom data structure */
- memset(&data, 0, sizeof(data));
- data.fps = fps;
- data.in_file_path = argv[1];
- /* Standard GStreamer initialization */
- gst_init(&argc, &argv);
- loop = g_main_loop_new(NULL, FALSE);
- /* Create gstreamer elements */
- pipeline = gst_pipeline_new("av_packet_reading");
- if (!pipeline)
- {
- g_printerr("Pipeline could not be created. Exiting.\n");
- return -1;
- }
- gchar *string = NULL;
- string = g_strdup_printf("appsrc name=app_source caps=\"%s\" ! decodebin ! videoconvert ! autovideosink", video_caps);
- // string = g_strdup_printf("appsrc name=app_source caps=\"%s\" ! h264parse ! videoconvert ! autovideosink", video_caps);
- // string = g_strdup_printf("appsrc name=app_source caps=\"%s\" ! theoradec ! videoconvert ! autovideosink", video_caps);
- pipeline = gst_parse_launch(string, NULL);
- g_free(string);
- if (pipeline == NULL)
- {
- g_print("Bad sink\n");
- return -1;
- }
- data.app_source = gst_bin_get_by_name(GST_BIN(pipeline), "app_source");
- bus = gst_element_get_bus(pipeline);
- gst_bus_add_watch(bus, (GstBusFunc)bus_call, loop);
- gst_object_unref(bus);
- // Run a thread to read data a from file and to feed the appsrc element.
- pthread_t thread_id;
- pthread_create(&thread_id, NULL, av_push_data, &data);
- gst_element_set_state(pipeline, GST_STATE_PLAYING);
- /* Pipeline is running. */
- g_main_loop_run(loop);
- gst_element_set_state(pipeline, GST_STATE_NULL);
- gst_object_unref(pipeline);
- g_main_loop_unref(loop);
- // pthread_exit(NULL);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement