Ticket #2716: muxing.c

File muxing.c, 6.7 KB (added by er.anshul.maheshwari@gmail.com, 3 years ago)

this file produce same result and have no dependency other then ffmpeg

Line 
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <math.h>
5
6#include <libxml/tree.h>
7#include <libavformat/avformat.h>
8#include <libavfilter/avfiltergraph.h>
9#include <libavfilter/avcodec.h>
10#include <libavfilter/buffersink.h>
11#include <libavfilter/buffersrc.h>
12#include <libavutil/avstring.h>
13#include <libswresample/swresample.h>
14#include <libavutil/opt.h>
15#include <libavutil/audio_fifo.h>
16
17
18struct mux_cfg
19{
20        codec_id;
21};
22/* test application dependency */
23struct mux_cfg *cfg;
24
25/* 5 seconds stream duration */
26#define STREAM_DURATION   200.0
27#define STREAM_FRAME_RATE 25 /* 25 images */
28#define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */
29/**************************************************************/
30
31/* application specific api */
32
33static int mux_read(void* opaque, char*buf, int size);
34static int mux_write(void* opaque, char*buf, int size);
35static int parse_xml(char*xml,struct mux_cfg *cfg);
36static int update_input_param(xmlNodePtr ParentNode, struct mux_cfg *cfg,xmlDocPtr doc);
37/* Add an output stream. */
38static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
39                struct mux_cfg cfg)
40{
41        AVCodecContext *c;
42        AVStream *st;
43
44        st = avformat_new_stream(oc, *codec);
45        if (!st)
46        {
47                fprintf(stderr, "Could not allocate stream\n");
48                exit(1);
49        }
50        st->id = oc->nb_streams - 1;
51        c = st->codec;
52
53        switch ((*codec)->type)
54        {
55        case AVMEDIA_TYPE_AUDIO:
56                st->id = 1;
57                c->codec_id = cfg.codec_id[1];
58                c->sample_fmt = AV_SAMPLE_FMT_S16;
59                c->bit_rate = 64000;
60//              c->bit_rate = 1;
61
62                c->sample_rate = cfg.audio_sample_rate;
63                c->channels = 2;
64//              c->channels = 1;
65
66                c->frame_size = 1024;
67//              c->frame_size = 0;
68
69                break;
70
71        case AVMEDIA_TYPE_VIDEO:
72                c->codec_id = cfg.codec_id[0];
73
74                c->bit_rate = 400000;
75                /* Resolution must be a multiple of two. */
76                c->width = 1280;
77                c->height = 720;
78                /* timebase: This is the fundamental unit of time (in seconds) in terms
79                 * of which frame timestamps are represented. For fixed-fps content,
80                 * timebase should be 1/framerate and timestamp increments should be
81                 * identical to 1. */
82                c->time_base.den = cfg.video_frame_rate;
83                c->time_base.num = 1;
84                c->gop_size = 12; /* emit one intra frame every twelve frames at most */
85                c->pix_fmt = STREAM_PIX_FMT;
86                break;
87
88        default:
89                break;
90        }
91
92        return st;
93}
94
95int init(char *xml)
96{
97        int i;
98        int ret = 0;
99        AVCodec *codec[MAX_STREAM];
100        i = 0;
101
102        memset(&cfg, 0, sizeof(cfg));
103        /* Initialize libavcodec, and register all codecs and formats. */
104        av_register_all();
105
106        parse_xml(xml,&cfg);
107
108        strcpy(cfg.output_filename, "test.ts");
109
110        /* allocate the output media context */
111        avformat_alloc_output_context2(&cfg.oc, NULL, "mpegts", NULL );
112        if (!cfg.oc)
113        {
114                printf("unable to allocate allocate context\n");
115        }
116
117        cfg.obuffer = malloc(1920 * 1080);
118
119        cfg.oc->pb = avio_alloc_context(cfg.obuffer, 1920 * 1080, AVIO_FLAG_WRITE,
120                        (void*) &cfg, (void*) mux_read, (void*) mux_write, NULL );
121        for (i = 0; i < cfg.no_of_stream; i++)
122        {
123
124                /* find the encoder */
125                codec[i] = avcodec_find_encoder(cfg.codec_id[i]);
126                if (!(codec[i]))
127                {
128                        fprintf(stderr, "Could not find encoder for '%s'\n",
129                                        avcodec_get_name(cfg.codec_id[i]));
130                        return -1;
131                }
132
133                cfg.st[i] = add_stream(cfg.oc, &codec[i], cfg);
134        }
135
136        /* Write the stream header, if any. */
137        ret = avformat_write_header(cfg.oc, NULL );
138        if (ret < 0)
139        {
140                fprintf(stderr, "Error occurred when opening output file: %s\n",
141                                av_err2str(ret));
142                return 1;
143        }
144
145        return 0;
146}
147
148int get_buffer(void *pOutputData,int64_t *pts)
149{
150
151        struct IOBuffer *buf = (void*) pOutputData;
152
153        if(pts)
154        {
155                *pts = cfg.uopts;
156        }
157
158        if (cfg.uosize == 0)
159        {
160                return 0;
161        }
162
163        buf->buffer = cfg.uobuffer;
164        buf->size = cfg.uosize;
165
166        cfg.uosize = 0;
167        if(pts)
168        {
169                *pts = cfg.uopts;
170        }
171
172        return buf->size;
173}
174int put_buffer(void *pInputData ,int64_t *pts,int id)
175{
176        struct IOBuffer *buf = (void*) pInputData;
177        int ret;
178        AVPacket pkt;
179
180        av_init_packet(&pkt);
181
182        pkt.data = buf->buffer;
183        pkt.size = buf->size;
184
185        if( pts && *pts)
186        {
187                pkt.pts = *pts;
188        }
189        pkt.stream_index = id;
190        ret = av_interleaved_write_frame(cfg.oc, &pkt);
191        if (ret < 0)
192        {
193                fprintf(stderr, "av_interleaved_write_frame     : %s\n", av_err2str(ret));
194        }
195        cfg.uopts = pkt.pts;
196        return ret;
197}
198
199static int mux_read(void* opaque, char*buf, int size)
200{
201        printf("inside mux read function\n");
202        return 0;
203}
204
205static int mux_write(void* opaque, char*buf, int size)
206{
207        memcpy(cfg.uobuffer + cfg.uosize, buf, size);
208        cfg.uosize += size;
209        return 0;
210
211}
212
213int dinit(void)
214{
215        /* Write the trailer, if any. The trailer must be written before you
216         * close the CodecContexts open when you wrote the header; otherwise
217         * av_write_trailer() may try to use memory that was freed on
218         * av_codec_close(). */
219        av_write_trailer(cfg.oc);
220
221
222        av_free(cfg.oc->pb);
223        /* free the stream */
224        avformat_free_context(cfg.oc);
225
226        return 0;
227
228}
229
230
231static int parse_xml(char*xml,struct mux_cfg *cfg)
232{
233        int ret = 0;
234        xmlDocPtr doc;
235        xmlNodePtr nl1;
236
237        if(!xml || !cfg)
238        {
239                ret= -1;
240                return ret;
241        }
242        doc = xmlParseFile(xml);
243        if (doc == NULL)
244        {
245                ret= -1;
246                return ret;
247
248        }
249        for (nl1 = doc->children; nl1 != NULL; nl1 = nl1->next)
250        {
251                        ret = xmlStrcmp(nl1->name, (const xmlChar *) "INPUT");
252                        if (ret == 0)
253                        {
254                                update_input_param(nl1,cfg,doc);
255                        }
256        }
257
258        xmlFreeDoc(doc);
259        return ret;
260}
261static int update_input_param(xmlNodePtr ParentNode, struct mux_cfg *cfg,xmlDocPtr doc)
262{
263
264        xmlNodePtr nl = ParentNode->children;
265        char *pXmlGetString = NULL;
266
267        int ret = 0;
268        for (; nl != NULL; nl = nl->next)
269        {
270                ret = xmlStrcmp(nl->name, (const xmlChar *) "no_of_elem_stream");
271                if (ret == 0)
272                {
273                        pXmlGetString = (char *) xmlNodeListGetString(doc,
274                                nl->xmlChildrenNode, 1);
275                        sscanf(pXmlGetString, "%d", &cfg->no_of_stream);
276                        xmlFree(pXmlGetString);
277
278                }
279
280                ret = xmlStrcmp(nl->name, (const xmlChar *) "audio_codec");
281                if (ret == 0)
282                {
283                        pXmlGetString = (char *) xmlNodeListGetString(doc,
284                                nl->xmlChildrenNode, 1);
285                        if(!strcmp(pXmlGetString,"aac"))
286                        {
287                                cfg->codec_id[1] = AV_CODEC_ID_AAC;
288                        }
289                        xmlFree(pXmlGetString);
290                }
291
292                ret = xmlStrcmp(nl->name, (const xmlChar *) "video_codec");
293                if (ret == 0)
294                {
295                        pXmlGetString = (char *) xmlNodeListGetString(doc,
296                                nl->xmlChildrenNode, 1);
297                        if(!strcmp(pXmlGetString,"h264"))
298                        {
299                                cfg->codec_id[0] = AV_CODEC_ID_H264;
300                        }
301                        xmlFree(pXmlGetString);
302
303                }
304
305                ret = xmlStrcmp(nl->name, (const xmlChar *) "audio_sample_rate");
306                if (ret == 0)
307                {
308                        pXmlGetString = (char *) xmlNodeListGetString(doc,
309                                nl->xmlChildrenNode, 1);
310                        sscanf(pXmlGetString, "%d", &cfg->audio_sample_rate);
311                        xmlFree(pXmlGetString);
312
313                }
314
315                ret = xmlStrcmp(nl->name, (const xmlChar *) "video_frame_rate");
316                if (ret == 0)
317                {
318                        pXmlGetString = (char *) xmlNodeListGetString(doc,
319                                nl->xmlChildrenNode, 1);
320                        sscanf(pXmlGetString, "%d", &cfg->video_frame_rate);
321                        xmlFree(pXmlGetString);
322
323                }
324
325
326        }
327        return ret;
328}
329