Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <pthread.h>
- #include "transcode.h"
- #include "subscription.h"
- #include "memwatch.h"
- void transcode_main_init(void) {
- avcodec_register_all();
- av_register_all();
- //show_codecs(); //show the available codecs
- Print("FFMPEG Engine initialised\n");
- return;
- }
- int transcode_write(struct transcode_t *ts, unsigned char *in_buffer,int length) {
- int rc=-1;
- pthread_mutex_lock(&ts->input.lock);
- if (ts->input.buffer_ptr < OUTPUT_BUFSIZE-length) {
- memcpy(ts->input.temp_buffer+ts->input.buffer_ptr,in_buffer,length);
- ts->input.buffer_ptr+=length;
- } else
- length=-1;
- pthread_mutex_unlock(&ts->input.lock);
- return length;
- }
- int read_input_packet(void *opaque, uint8_t *buf, int buf_size) {
- int copylen=0;
- struct subs_users_t *subs_user = opaque;
- while (subs_user->transcode->input.buffer_ptr == 0) {
- usleep(10000);
- }
- // Print(">>>>>>>>> %s [%d]\n",__FUNCTION__,subs_user->transcode->input.buffer_ptr);
- if (subs_user->transcode->input.buffer_ptr > 0) {
- pthread_mutex_lock(&subs_user->transcode->input.lock);
- if (subs_user->transcode->input.buffer_ptr > buf_size) {
- copylen=buf_size;
- } else {
- copylen=subs_user->transcode->input.buffer_ptr;
- }
- memcpy(buf,subs_user->transcode->input.temp_buffer,copylen);
- subs_user->transcode->input.buffer_ptr-=copylen;
- memmove(subs_user->transcode->input.temp_buffer,&subs_user->transcode->input.temp_buffer[copylen],
- subs_user->transcode->input.buffer_ptr);
- pthread_mutex_unlock(&subs_user->transcode->input.lock);
- }
- return copylen;
- }
- int start_transcode_reader(struct subs_users_t *subs_user) {
- pthread_attr_t attr;
- Print("%s\n",__FUNCTION__);
- subs_user->transcode->input.buffer_ptr=0;
- pthread_attr_init ( &attr );
- pthread_attr_setdetachstate ( &attr, PTHREAD_CREATE_DETACHED );
- transcode_init_InputData(subs_user->transcode,subs_user);
- subs_user->transcode->thread_id = pthread_create ( &subs_user->transcode->transcode_thread, &attr,main_transcode_thread, subs_user );
- return 1;
- }
- int transcode_init_InputData(struct transcode_t *ts, void *subs_user) {
- int rc = -1;
- pthread_mutex_init(&ts->input.lock,NULL);
- ts->input.io = av_alloc_put_byte(ts->input.input_buffer, BUFFER_SIZE, 0, subs_user,read_input_packet,NULL,NULL);
- ts->input.format = av_find_input_format("mpegts");
- if (NULL == ts->input.format) {
- Print("Couldn't find input format.\n");
- return rc;
- }
- return 1;
- }
- int write_output_packet(void *opaque, uint8_t *buf, int buf_size) {
- int rc = buf_size;
- struct subs_users_t *su = opaque;
- if (su->header == 0)
- {
- su->header == 1; // MP4 header
- //write(su->user_handle,"moov",4);
- }
- if (su->user_handle > 0)
- {
- if (su->transcode->transcode_ptr+buf_size >= 1024*1024*5)
- su->transcode->transcode_ptr = 0;
- memcpy(su->transcode->transcode_output+su->transcode->transcode_ptr,buf,buf_size);
- su->transcode->transcode_ptr += buf_size;
- rc = write(su->user_handle,su->transcode->transcode_output,su->transcode->transcode_ptr);
- if (rc > 0)
- {
- //Print("Loaded buf_size %d.. wrote %d\n",buf_size,rc);
- su->transcode->transcode_ptr -= rc;
- memmove(su->transcode->transcode_output,&su->transcode->transcode_output[rc],su->transcode->transcode_ptr);
- }
- }
- return buf_size;
- }
- void *main_transcode_thread(void *ptr) {
- struct subs_users_t *subs_user = ptr;
- Print("Transcode thread started\n");
- if (0 != av_open_input_stream(&subs_user->transcode->input.context, subs_user->transcode->input.io, "stream",
- subs_user->transcode->input.format, NULL)) {
- Print("Couldn't open input stream.\n");
- pthread_exit(0);
- }
- if (0 > av_find_stream_info(subs_user->transcode->input.context)) {
- Print("Couldn't find stream information.\n");
- pthread_exit(0);
- }
- //Print("Streams detected %i\n",subs_user->transcode->input.context->nb_streams);
- //dump_format(subs_user->transcode->input.context, 0, "stream", 0);
- int i;
- for (i = 0; i < subs_user->transcode->input.context->nb_streams; i++) {
- AVStream *in_stream = subs_user->transcode->input.context->streams[i];
- if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type || AVMEDIA_TYPE_AUDIO == in_stream->codec->codec_type) {
- AVCodec *codec = avcodec_find_decoder(in_stream->codec->codec_id);
- if (NULL == codec) {
- Print("Couldn't find codec for decoding.\n");
- continue;
- }
- if (0 > avcodec_open(in_stream->codec, codec)) {
- Print("Couldn't open codec for decoding.\n");
- continue;
- }
- }
- }
- init_outputData(subs_user);
- AVPacket packet;
- for(;;) {
- if (0 > av_read_frame(subs_user->transcode->input.context, &packet)) {
- printf("Ending transcoding - av_read_frame returned error.\n");
- break;
- }
- AVStream *in_stream = subs_user->transcode->input.context->streams[packet.stream_index];
- AVFrame *frame = avcodec_alloc_frame();
- if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type) {
- /* Decode video */
- int is_frame_finished=0;
- int bytes_decoded = avcodec_decode_video2(in_stream->codec,frame, &is_frame_finished, &packet);
- if (is_frame_finished) {
- frame->pict_type = 0;
- frame->quality = subs_user->transcode->output.video_st->codec->global_quality;
- int out_size = avcodec_encode_video(subs_user->transcode->output.video_st->codec,
- subs_user->transcode->output.video_outbuf,
- subs_user->transcode->output.video_outbuf_size,frame);
- if (out_size > 0) {
- AVPacket pkt;
- av_init_packet(&pkt);
- AVCodecContext *c = subs_user->transcode->output.video_st->codec;
- if (c->coded_frame->pts != AV_NOPTS_VALUE)
- pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, subs_user->transcode->output.video_st->time_base);
- if(c->coded_frame->key_frame)
- pkt.flags |= AV_PKT_FLAG_KEY;
- pkt.stream_index= subs_user->transcode->output.video_st->index;
- pkt.data= subs_user->transcode->output.video_outbuf;
- pkt.size= out_size;
- /* write the compressed frame in the media file */
- int ret = av_write_frame(subs_user->transcode->output.oc, &pkt);
- }
- }
- av_free(frame);
- }
- if (AVMEDIA_TYPE_AUDIO == in_stream->codec->codec_type) {
- /* Decode video */
- int16_t *audio_samples = av_malloc(AUDIO_TRANSCODE_BUFSIZE);
- int sample_size=AUDIO_TRANSCODE_BUFSIZE;
- int bytes_decoded = avcodec_decode_audio3(in_stream->codec,audio_samples, &sample_size, &packet);
- if (bytes_decoded > 0) {
- Print("Pts/Dts -> %llu/%llu\n",packet.pts,packet.dts);
- int rc= avcodec_encode_audio(subs_user->transcode->output.audio_st->codec,
- subs_user->transcode->output.audio_outbuf,
- subs_user->transcode->output.audio_outbuf_size,
- audio_samples);
- #if 1
- if (rc > 0)
- {
- AVPacket pkt;
- AVCodecContext *c;
- av_init_packet(&pkt);
- c = subs_user->transcode->output.audio_st->codec;
- if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
- pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, subs_user->transcode->output.audio_st->time_base);
- pkt.flags |= AV_PKT_FLAG_KEY;
- pkt.size = rc;
- pkt.stream_index= subs_user->transcode->output.video_st->index;
- pkt.data= subs_user->transcode->output.audio_outbuf;
- int ret = av_write_frame(subs_user->transcode->output.oc, &pkt);
- }
- #endif
- }
- av_free(audio_samples);
- }
- }
- pthread_exit(0);
- }
- //================================ HERE ==============================
- static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id,AVStream *in_stream) {
- AVCodecContext *c;
- AVStream *st;
- st = av_new_stream(oc, 1);
- if (!st) {
- fprintf(stderr, "Could not alloc stream\n");
- return;
- }
- c = st->codec;
- c->codec_id = codec_id;
- c->codec_type = AVMEDIA_TYPE_AUDIO;
- /* put sample parameters */
- //c->bit_rate = 64000;
- //c->sample_rate = 44100;
- //c->channels = 2;
- c->bit_rate = in_stream->codec->bit_rate;
- c->channels = in_stream->codec->channels;
- c->sample_rate = in_stream->codec->sample_rate;
- c->sample_fmt = in_stream->codec->sample_fmt;
- // some formats want stream headers to be separate
- if(oc->oformat->flags & AVFMT_GLOBALHEADER)
- c->flags |= CODEC_FLAG_GLOBAL_HEADER;
- return st;
- }
- static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id, AVStream *in_stream) {
- AVCodecContext *c;
- AVStream *st;
- st = av_new_stream(oc, 0);
- if (!st) {
- fprintf(stderr, "Could not alloc stream\n");
- return NULL;
- }
- c = st->codec;
- Print("Created Codec ptr is %p\n",c);
- avcodec_get_context_defaults2(c, AVMEDIA_TYPE_VIDEO);
- c->codec_id = codec_id;
- c->codec_type = AVMEDIA_TYPE_VIDEO;
- /* put sample parameters */
- c->bit_rate = 100000;
- /* resolution must be a multiple of two */
- c->width = in_stream->codec->width;
- c->height = in_stream->codec->height;
- /* time base: this is the fundamental unit of time (in seconds) in terms
- of which frame timestamps are represented. for fixed-fps content,
- timebase should be 1/framerate and timestamp increments should be
- identically 1. */
- c->sample_aspect_ratio = in_stream->sample_aspect_ratio;
- st->sample_aspect_ratio = c->sample_aspect_ratio;
- st->codec->flags |= CODEC_FLAG_QSCALE;
- st->codec->global_quality = FF_QP2LAMBDA*30; //15 was ok
- c->time_base.num = in_stream->r_frame_rate.den;
- c->time_base.den = in_stream->r_frame_rate.num;
- c->gop_size = 5;
- c->pix_fmt = PIX_FMT_YUV420P;
- //if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
- /* just for testing, we also add B frames */
- //c->max_b_frames = 5;
- //}
- if (c->codec_id == CODEC_ID_MPEG1VIDEO) {
- /* Needed to avoid using macroblocks in which some coeffs overflow.
- This does not happen with normal video, it just happens here as
- the motion of the chroma plane does not match the luma plane. */
- c->mb_decision=2;
- }
- // some formats want stream headers to be separate
- if(oc->oformat->flags & AVFMT_GLOBALHEADER)
- c->flags |= CODEC_FLAG_GLOBAL_HEADER;
- return st;
- }
- int init_outputData(struct subs_users_t *subs) {
- struct transcode_t *ts = subs->transcode;
- //ts->output.fmt = av_guess_format("mpegts", NULL, NULL);
- ts->output.fmt = av_guess_format("mpegts", NULL, NULL);
- ts->output.oc = avformat_alloc_context();
- ts->output.oc->oformat = ts->output.fmt;
- AVIOContext *output_io = avio_alloc_context(ts->output.io_buffer,1024*10, 1, subs,NULL,write_output_packet,NULL);
- output_io->is_streamed = 1; /* Disallow seek operations */
- output_io->max_packet_size = OUTPUT_BUFSIZE; /* TODO: am I right? */
- ts->output.oc->pb=output_io;
- ts->output.oc->debug=0;
- ts->output.video_st = NULL;
- ts->output.audio_st = NULL;
- int i;
- Print("Parsing %d streams\n",subs->transcode->input.context->nb_streams);
- for (i=0; i < subs->transcode->input.context->nb_streams; i++) {
- AVStream *in_stream = subs->transcode->input.context->streams[i];
- }
- for (i=0; i < subs->transcode->input.context->nb_streams; i++) {
- AVStream *in_stream = subs->transcode->input.context->streams[i];
- if (AVMEDIA_TYPE_VIDEO == in_stream->codec->codec_type) {
- if (ts->output.video_st == NULL) {
- AVCodec *codec = avcodec_find_encoder_by_name("mpeg1video");
- // CODEC_ID_MPEG4
- ts->output.video_st = add_video_stream(ts->output.oc, codec->id,in_stream);
- }
- }
- if (AVMEDIA_TYPE_AUDIO == in_stream->codec->codec_type) {
- if (ts->output.audio_st==NULL) {
- AVCodec *codec = avcodec_find_encoder_by_name("mp2");
- ts->output.audio_st = add_audio_stream(ts->output.oc, codec->id,in_stream);
- }
- }
- } // end of FOR loop
- if (av_set_parameters(ts->output.oc, NULL) < 0) {
- fprintf(stderr, "Invalid output format parameters\n");
- return -1;
- }
- if (ts->output.video_st)
- open_video(ts->output.oc, ts->output.video_st, subs->transcode);
- if (ts->output.audio_st)
- open_audio(ts->output.oc, ts->output.audio_st,subs->transcode);
- dump_format(ts->output.oc, 0,"Output Stream", 1);
- av_write_header(ts->output.oc);
- Print("%s -> EXIT\n",__FUNCTION__);
- return 1;
- }
- void open_audio(AVFormatContext *oc, AVStream *st,struct transcode_t *ts) {
- AVCodecContext *c;
- AVCodec *codec;
- c = st->codec;
- Print("Audio CodecID is %d\n",c->codec_id);
- /* find the audio encoder */
- codec = avcodec_find_encoder(c->codec_id);
- if (!codec) {
- fprintf(stderr, "codec not found\n");
- return;
- }
- /* open it */
- if (avcodec_open(c, codec) < 0) {
- fprintf(stderr, "could not open AUDIO codec\n");
- return;
- }
- ts->output.audio_outbuf_size = 200000;
- ts->output.audio_outbuf = av_malloc(ts->output.audio_outbuf_size);
- return;
- }
- void open_video(AVFormatContext *oc, AVStream *st, struct transcode_t *ts) {
- AVCodec *codec;
- AVCodecContext *c;
- c = st->codec;
- /* find the video encoder */
- Print("Video CodecID is %d\n",c->codec_id);
- codec = avcodec_find_encoder(c->codec_id);
- if (!codec) {
- fprintf(stderr, "codec not found\n");
- return;
- }
- /* open the codec */
- if (avcodec_open(c, codec) < 0) {
- fprintf(stderr, "could not open codec\n");
- return;
- }
- ts->output.video_outbuf_size = 200000;
- ts->output.video_outbuf = av_malloc(ts->output.video_outbuf_size);
- Print("%s StreamCodec Ptr %p\n",__FUNCTION__,c);
- return;
- }
- AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) {
- AVFrame *picture;
- uint8_t *picture_buf;
- int size;
- picture = avcodec_alloc_frame();
- if (!picture)
- return NULL;
- size = avpicture_get_size(pix_fmt, width, height);
- picture_buf = av_malloc(size);
- if (!picture_buf) {
- av_free(picture);
- return NULL;
- }
- avpicture_fill((AVPicture *)picture, picture_buf,
- pix_fmt, width, height);
- return picture;
- }
- void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height) {
- int x, y, i;
- i = frame_index;
- /* Y */
- for(y=0; y<height; y++) {
- for(x=0; x<width; x++) {
- pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
- }
- }
- /* Cb and Cr */
- for(y=0; y<height/2; y++) {
- for(x=0; x<width/2; x++) {
- pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
- pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement