Advertisement
Guest User

Untitled

a guest
Oct 28th, 2011
356
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.26 KB | None | 0 0
  1. #include <pthread.h>
  2.  
  3. #include "transcode.h"
  4. #include "subscription.h"
  5. #include "memwatch.h"
  6.  
  7. void transcode_main_init(void) {
  8. avcodec_register_all();
  9. av_register_all();
  10. //show_codecs(); //show the available codecs
  11. Print("FFMPEG Engine initialised\n");
  12.  
  13. return;
  14. }
  15.  
  16. int transcode_write(struct transcode_t *ts, unsigned char *in_buffer,int length) {
  17. int rc=-1;
  18.  
  19. pthread_mutex_lock(&ts->input.lock);
  20. if (ts->input.buffer_ptr < OUTPUT_BUFSIZE-length) {
  21. memcpy(ts->input.temp_buffer+ts->input.buffer_ptr,in_buffer,length);
  22. ts->input.buffer_ptr+=length;
  23. } else
  24. length=-1;
  25.  
  26. pthread_mutex_unlock(&ts->input.lock);
  27.  
  28. return length;
  29. }
  30.  
  31.  
  32. int read_input_packet(void *opaque, uint8_t *buf, int buf_size) {
  33.  
  34. int copylen=0;
  35. struct subs_users_t *subs_user = opaque;
  36.  
  37. while (subs_user->transcode->input.buffer_ptr == 0) {
  38. usleep(10000);
  39. }
  40. // Print(">>>>>>>>> %s [%d]\n",__FUNCTION__,subs_user->transcode->input.buffer_ptr);
  41.  
  42. if (subs_user->transcode->input.buffer_ptr > 0) {
  43. pthread_mutex_lock(&subs_user->transcode->input.lock);
  44.  
  45. if (subs_user->transcode->input.buffer_ptr > buf_size) {
  46. copylen=buf_size;
  47. } else {
  48. copylen=subs_user->transcode->input.buffer_ptr;
  49. }
  50.  
  51. memcpy(buf,subs_user->transcode->input.temp_buffer,copylen);
  52. subs_user->transcode->input.buffer_ptr-=copylen;
  53.  
  54. memmove(subs_user->transcode->input.temp_buffer,&subs_user->transcode->input.temp_buffer[copylen],
  55. subs_user->transcode->input.buffer_ptr);
  56.  
  57. pthread_mutex_unlock(&subs_user->transcode->input.lock);
  58. }
  59. return copylen;
  60. }
  61.  
  62.  
  63. int start_transcode_reader(struct subs_users_t *subs_user) {
  64.  
  65. pthread_attr_t attr;
  66.  
  67. Print("%s\n",__FUNCTION__);
  68. subs_user->transcode->input.buffer_ptr=0;
  69. pthread_attr_init ( &attr );
  70. pthread_attr_setdetachstate ( &attr, PTHREAD_CREATE_DETACHED );
  71.  
  72. transcode_init_InputData(subs_user->transcode,subs_user);
  73.  
  74. subs_user->transcode->thread_id = pthread_create ( &subs_user->transcode->transcode_thread, &attr,main_transcode_thread, subs_user );
  75.  
  76. return 1;
  77. }
  78.  
  79. int transcode_init_InputData(struct transcode_t *ts, void *subs_user) {
  80. int rc = -1;
  81. pthread_mutex_init(&ts->input.lock,NULL);
  82.  
  83. ts->input.io = av_alloc_put_byte(ts->input.input_buffer, BUFFER_SIZE, 0, subs_user,read_input_packet,NULL,NULL);
  84. ts->input.format = av_find_input_format("mpegts");
  85. if (NULL == ts->input.format) {
  86. Print("Couldn't find input format.\n");
  87. return rc;
  88. }
  89. return 1;
  90. }
  91.  
  92. int write_output_packet(void *opaque, uint8_t *buf, int buf_size) {
  93.  
  94. int rc = buf_size;
  95. struct subs_users_t *su = opaque;
  96. if (su->header == 0)
  97. {
  98. su->header == 1; // MP4 header
  99. //write(su->user_handle,"moov",4);
  100. }
  101.  
  102. if (su->user_handle > 0)
  103. {
  104. if (su->transcode->transcode_ptr+buf_size >= 1024*1024*5)
  105. su->transcode->transcode_ptr = 0;
  106.  
  107. memcpy(su->transcode->transcode_output+su->transcode->transcode_ptr,buf,buf_size);
  108. su->transcode->transcode_ptr += buf_size;
  109.  
  110. rc = write(su->user_handle,su->transcode->transcode_output,su->transcode->transcode_ptr);
  111. if (rc > 0)
  112. {
  113. //Print("Loaded buf_size %d.. wrote %d\n",buf_size,rc);
  114. su->transcode->transcode_ptr -= rc;
  115. memmove(su->transcode->transcode_output,&su->transcode->transcode_output[rc],su->transcode->transcode_ptr);
  116. }
  117. }
  118. return buf_size;
  119. }
  120.  
  121.  
  122.  
  123.  
  124. void *main_transcode_thread(void *ptr) {
  125.  
  126. struct subs_users_t *subs_user = ptr;
  127.  
  128. Print("Transcode thread started\n");
  129.  
  130. if (0 != av_open_input_stream(&subs_user->transcode->input.context, subs_user->transcode->input.io, "stream",
  131. subs_user->transcode->input.format, NULL)) {
  132. Print("Couldn't open input stream.\n");
  133. pthread_exit(0);
  134. }
  135.  
  136. if (0 > av_find_stream_info(subs_user->transcode->input.context)) {
  137. Print("Couldn't find stream information.\n");
  138. pthread_exit(0);
  139. }
  140. //Print("Streams detected %i\n",subs_user->transcode->input.context->nb_streams);
  141. //dump_format(subs_user->transcode->input.context, 0, "stream", 0);
  142.  
  143. int i;
  144. for (i = 0; i < subs_user->transcode->input.context->nb_streams; i++) {
  145. AVStream *in_stream = subs_user->transcode->input.context->streams[i];
  146. if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type || AVMEDIA_TYPE_AUDIO == in_stream->codec->codec_type) {
  147.  
  148. AVCodec *codec = avcodec_find_decoder(in_stream->codec->codec_id);
  149. if (NULL == codec) {
  150. Print("Couldn't find codec for decoding.\n");
  151. continue;
  152. }
  153. if (0 > avcodec_open(in_stream->codec, codec)) {
  154. Print("Couldn't open codec for decoding.\n");
  155. continue;
  156. }
  157.  
  158. }
  159. }
  160.  
  161.  
  162. init_outputData(subs_user);
  163.  
  164. AVPacket packet;
  165. for(;;) {
  166. if (0 > av_read_frame(subs_user->transcode->input.context, &packet)) {
  167. printf("Ending transcoding - av_read_frame returned error.\n");
  168. break;
  169. }
  170.  
  171. AVStream *in_stream = subs_user->transcode->input.context->streams[packet.stream_index];
  172. AVFrame *frame = avcodec_alloc_frame();
  173. if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type) {
  174. /* Decode video */
  175. int is_frame_finished=0;
  176. int bytes_decoded = avcodec_decode_video2(in_stream->codec,frame, &is_frame_finished, &packet);
  177. if (is_frame_finished) {
  178.  
  179. frame->pict_type = 0;
  180. frame->quality = subs_user->transcode->output.video_st->codec->global_quality;
  181.  
  182. int out_size = avcodec_encode_video(subs_user->transcode->output.video_st->codec,
  183. subs_user->transcode->output.video_outbuf,
  184. subs_user->transcode->output.video_outbuf_size,frame);
  185. if (out_size > 0) {
  186.  
  187. AVPacket pkt;
  188. av_init_packet(&pkt);
  189. AVCodecContext *c = subs_user->transcode->output.video_st->codec;
  190.  
  191. if (c->coded_frame->pts != AV_NOPTS_VALUE)
  192. pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, subs_user->transcode->output.video_st->time_base);
  193. if(c->coded_frame->key_frame)
  194. pkt.flags |= AV_PKT_FLAG_KEY;
  195.  
  196. pkt.stream_index= subs_user->transcode->output.video_st->index;
  197. pkt.data= subs_user->transcode->output.video_outbuf;
  198. pkt.size= out_size;
  199.  
  200. /* write the compressed frame in the media file */
  201. int ret = av_write_frame(subs_user->transcode->output.oc, &pkt);
  202. }
  203. }
  204. av_free(frame);
  205. }
  206. if (AVMEDIA_TYPE_AUDIO == in_stream->codec->codec_type) {
  207. /* Decode video */
  208. int16_t *audio_samples = av_malloc(AUDIO_TRANSCODE_BUFSIZE);
  209. int sample_size=AUDIO_TRANSCODE_BUFSIZE;
  210. int bytes_decoded = avcodec_decode_audio3(in_stream->codec,audio_samples, &sample_size, &packet);
  211. if (bytes_decoded > 0) {
  212. Print("Pts/Dts -> %llu/%llu\n",packet.pts,packet.dts);
  213.  
  214. int rc= avcodec_encode_audio(subs_user->transcode->output.audio_st->codec,
  215. subs_user->transcode->output.audio_outbuf,
  216. subs_user->transcode->output.audio_outbuf_size,
  217. audio_samples);
  218. #if 1
  219. if (rc > 0)
  220. {
  221. AVPacket pkt;
  222. AVCodecContext *c;
  223. av_init_packet(&pkt);
  224.  
  225. c = subs_user->transcode->output.audio_st->codec;
  226.  
  227. if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
  228. pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, subs_user->transcode->output.audio_st->time_base);
  229.  
  230. pkt.flags |= AV_PKT_FLAG_KEY;
  231. pkt.size = rc;
  232. pkt.stream_index= subs_user->transcode->output.video_st->index;
  233. pkt.data= subs_user->transcode->output.audio_outbuf;
  234. int ret = av_write_frame(subs_user->transcode->output.oc, &pkt);
  235. }
  236. #endif
  237.  
  238.  
  239. }
  240.  
  241. av_free(audio_samples);
  242. }
  243.  
  244.  
  245.  
  246.  
  247. }
  248. pthread_exit(0);
  249. }
  250.  
  251.  
  252.  
  253. //================================ HERE ==============================
  254.  
  255. static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id,AVStream *in_stream) {
  256. AVCodecContext *c;
  257. AVStream *st;
  258.  
  259. st = av_new_stream(oc, 1);
  260. if (!st) {
  261. fprintf(stderr, "Could not alloc stream\n");
  262. return;
  263. }
  264.  
  265. c = st->codec;
  266. c->codec_id = codec_id;
  267. c->codec_type = AVMEDIA_TYPE_AUDIO;
  268.  
  269.  
  270. /* put sample parameters */
  271. //c->bit_rate = 64000;
  272. //c->sample_rate = 44100;
  273. //c->channels = 2;
  274.  
  275. c->bit_rate = in_stream->codec->bit_rate;
  276. c->channels = in_stream->codec->channels;
  277. c->sample_rate = in_stream->codec->sample_rate;
  278. c->sample_fmt = in_stream->codec->sample_fmt;
  279.  
  280.  
  281. // some formats want stream headers to be separate
  282. if(oc->oformat->flags & AVFMT_GLOBALHEADER)
  283. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  284.  
  285. return st;
  286. }
  287.  
  288.  
  289. static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id, AVStream *in_stream) {
  290. AVCodecContext *c;
  291. AVStream *st;
  292.  
  293. st = av_new_stream(oc, 0);
  294. if (!st) {
  295. fprintf(stderr, "Could not alloc stream\n");
  296. return NULL;
  297. }
  298.  
  299. c = st->codec;
  300. Print("Created Codec ptr is %p\n",c);
  301.  
  302. avcodec_get_context_defaults2(c, AVMEDIA_TYPE_VIDEO);
  303.  
  304. c->codec_id = codec_id;
  305. c->codec_type = AVMEDIA_TYPE_VIDEO;
  306.  
  307. /* put sample parameters */
  308. c->bit_rate = 100000;
  309. /* resolution must be a multiple of two */
  310. c->width = in_stream->codec->width;
  311. c->height = in_stream->codec->height;
  312. /* time base: this is the fundamental unit of time (in seconds) in terms
  313. of which frame timestamps are represented. for fixed-fps content,
  314. timebase should be 1/framerate and timestamp increments should be
  315. identically 1. */
  316.  
  317. c->sample_aspect_ratio = in_stream->sample_aspect_ratio;
  318. st->sample_aspect_ratio = c->sample_aspect_ratio;
  319.  
  320. st->codec->flags |= CODEC_FLAG_QSCALE;
  321. st->codec->global_quality = FF_QP2LAMBDA*30; //15 was ok
  322.  
  323.  
  324. c->time_base.num = in_stream->r_frame_rate.den;
  325. c->time_base.den = in_stream->r_frame_rate.num;
  326. c->gop_size = 5;
  327.  
  328.  
  329. c->pix_fmt = PIX_FMT_YUV420P;
  330. //if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
  331. /* just for testing, we also add B frames */
  332. //c->max_b_frames = 5;
  333. //}
  334. if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
  335. /* Needed to avoid using macroblocks in which some coeffs overflow.
  336. This does not happen with normal video, it just happens here as
  337. the motion of the chroma plane does not match the luma plane. */
  338. c->mb_decision=2;
  339. }
  340. // some formats want stream headers to be separate
  341. if(oc->oformat->flags & AVFMT_GLOBALHEADER)
  342. c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  343.  
  344. return st;
  345. }
  346.  
  347.  
  348. int init_outputData(struct subs_users_t *subs) {
  349. struct transcode_t *ts = subs->transcode;
  350.  
  351. //ts->output.fmt = av_guess_format("mpegts", NULL, NULL);
  352. ts->output.fmt = av_guess_format("mpegts", NULL, NULL);
  353. ts->output.oc = avformat_alloc_context();
  354.  
  355. ts->output.oc->oformat = ts->output.fmt;
  356. AVIOContext *output_io = avio_alloc_context(ts->output.io_buffer,1024*10, 1, subs,NULL,write_output_packet,NULL);
  357.  
  358. output_io->is_streamed = 1; /* Disallow seek operations */
  359. output_io->max_packet_size = OUTPUT_BUFSIZE; /* TODO: am I right? */
  360. ts->output.oc->pb=output_io;
  361.  
  362. ts->output.oc->debug=0;
  363. ts->output.video_st = NULL;
  364. ts->output.audio_st = NULL;
  365.  
  366. int i;
  367. Print("Parsing %d streams\n",subs->transcode->input.context->nb_streams);
  368.  
  369. for (i=0; i < subs->transcode->input.context->nb_streams; i++) {
  370. AVStream *in_stream = subs->transcode->input.context->streams[i];
  371. }
  372.  
  373.  
  374. for (i=0; i < subs->transcode->input.context->nb_streams; i++) {
  375. AVStream *in_stream = subs->transcode->input.context->streams[i];
  376. if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type) {
  377. if (ts->output.video_st == NULL) {
  378.  
  379. AVCodec *codec = avcodec_find_encoder_by_name("mpeg1video");
  380. // CODEC_ID_MPEG4
  381. ts->output.video_st = add_video_stream(ts->output.oc, codec->id,in_stream);
  382. }
  383. }
  384.  
  385. if (AVMEDIA_TYPE_AUDIO == in_stream->codec->codec_type) {
  386. if (ts->output.audio_st==NULL) {
  387. AVCodec *codec = avcodec_find_encoder_by_name("mp2");
  388. ts->output.audio_st = add_audio_stream(ts->output.oc, codec->id,in_stream);
  389. }
  390. }
  391.  
  392. } // end of FOR loop
  393.  
  394. if (av_set_parameters(ts->output.oc, NULL) < 0) {
  395. fprintf(stderr, "Invalid output format parameters\n");
  396. return -1;
  397. }
  398.  
  399.  
  400. if (ts->output.video_st)
  401. open_video(ts->output.oc, ts->output.video_st, subs->transcode);
  402.  
  403. if (ts->output.audio_st)
  404. open_audio(ts->output.oc, ts->output.audio_st,subs->transcode);
  405.  
  406. dump_format(ts->output.oc, 0,"Output Stream", 1);
  407. av_write_header(ts->output.oc);
  408.  
  409. Print("%s -> EXIT\n",__FUNCTION__);
  410. return 1;
  411. }
  412.  
  413. void open_audio(AVFormatContext *oc, AVStream *st,struct transcode_t *ts) {
  414. AVCodecContext *c;
  415. AVCodec *codec;
  416.  
  417. c = st->codec;
  418. Print("Audio CodecID is %d\n",c->codec_id);
  419. /* find the audio encoder */
  420. codec = avcodec_find_encoder(c->codec_id);
  421. if (!codec) {
  422. fprintf(stderr, "codec not found\n");
  423. return;
  424. }
  425.  
  426. /* open it */
  427. if (avcodec_open(c, codec) < 0) {
  428. fprintf(stderr, "could not open AUDIO codec\n");
  429. return;
  430. }
  431.  
  432. ts->output.audio_outbuf_size = 200000;
  433. ts->output.audio_outbuf = av_malloc(ts->output.audio_outbuf_size);
  434.  
  435. return;
  436. }
  437.  
  438. void open_video(AVFormatContext *oc, AVStream *st, struct transcode_t *ts) {
  439. AVCodec *codec;
  440. AVCodecContext *c;
  441.  
  442. c = st->codec;
  443.  
  444. /* find the video encoder */
  445. Print("Video CodecID is %d\n",c->codec_id);
  446. codec = avcodec_find_encoder(c->codec_id);
  447. if (!codec) {
  448. fprintf(stderr, "codec not found\n");
  449. return;
  450. }
  451.  
  452. /* open the codec */
  453. if (avcodec_open(c, codec) < 0) {
  454. fprintf(stderr, "could not open codec\n");
  455. return;
  456. }
  457.  
  458. ts->output.video_outbuf_size = 200000;
  459. ts->output.video_outbuf = av_malloc(ts->output.video_outbuf_size);
  460.  
  461.  
  462. Print("%s StreamCodec Ptr %p\n",__FUNCTION__,c);
  463. return;
  464. }
  465.  
  466. AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) {
  467. AVFrame *picture;
  468. uint8_t *picture_buf;
  469. int size;
  470.  
  471. picture = avcodec_alloc_frame();
  472. if (!picture)
  473. return NULL;
  474. size = avpicture_get_size(pix_fmt, width, height);
  475. picture_buf = av_malloc(size);
  476. if (!picture_buf) {
  477. av_free(picture);
  478. return NULL;
  479. }
  480. avpicture_fill((AVPicture *)picture, picture_buf,
  481. pix_fmt, width, height);
  482. return picture;
  483. }
  484.  
  485. void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) {
  486. int x, y, i;
  487.  
  488. i = frame_index;
  489.  
  490. /* Y */
  491. for(y=0; y<height; y++) {
  492. for(x=0; x<width; x++) {
  493. pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
  494. }
  495. }
  496.  
  497. /* Cb and Cr */
  498. for(y=0; y<height/2; y++) {
  499. for(x=0; x<width/2; x++) {
  500. pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
  501. pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
  502. }
  503. }
  504. }
  505.  
  506.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement