Ticket #2716: muxing.c

File muxing.c, 6.7 KB (added by er.anshul.maheshwari@gmail.com, 12 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