mnguyen

trouble with merging audio

Sep 13th, 2014
215
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "com_hlcam_video_services_RenderService.h"
  2.  
  3. #include <fstream>
  4. #include <vector>
  5. #include <string>
  6. #include <cstdlib>
  7. #include <iostream>
  8.  
  9. #include <hlcam/pixels/clip.h>
  10. #include <hlcam/pixels/vulcanRender.h>
  11.  
  12. #include <hlcam-common.h>
  13. #include <hlcam/communication/movie/movie.pb.h>
  14. using std::string;
  15.  
  16. #ifdef __cplusplus
  17. extern "C" {
  18. #include <libavutil/avassert.h>
  19. #include <libavutil/channel_layout.h>
  20. #include <libavutil/opt.h>
  21. #include <libavutil/mathematics.h>
  22. #include <libavformat/avformat.h>
  23. #include <libswscale/swscale.h>
  24. #include <libswresample/swresample.h>
  25.  
  26.  
  27. #define STREAM_DURATION   10.0
  28. #define STREAM_FRAME_RATE 25 /* 25 images/s */
  29. #define STREAM_PIX_FMT    AV_PIX_FMT_YUV420P /* default pix_fmt */
  30. #define SCALE_FLAGS SWS_BICUBIC
  31.  
  32. #endif
  33.  
  34. static bool marshal_resource_array(JNIEnv *env, movieRequest &request,
  35.                                              jobjectArray j_resources);
  36.  
  37. static clip * marshal_resource_to_clip(JNIEnv *env, const jobject &j_resource);
  38.  
  39. static clip * marshal_video(JNIEnv *env, const jobject &j_resource);
  40.  
  41. static clip * marshal_image(JNIEnv *env, const jobject &j_resource);
  42.  
  43. static clip * marshal_audio(JNIEnv *env, const jobject &j_resource);
  44.  
  45. static clip * marshal_text(JNIEnv *env, const jobject &j_resource);
  46.  
  47. static void marshal_soundtrack(JNIEnv *env, const jobject &j_soundtrack,
  48.                                string &soundtrack_path, float &ratio);
  49.  
  50. static string marshal_jstring_to_string(JNIEnv *env, const jstring &j_str);
  51.  
  52. static int marshal_jstring_to_int(JNIEnv *env, const jstring &j_str);
  53.  
  54. //static void marshal_color(JNIEnv *env, const jobject &j_color, float &r, float &g, float &b);
  55.  
  56. int com_hlcam_renderer_server_internal_RenderJob_RESULT_ERROR = -1;
  57. int com_hlcam_renderer_server_internal_RenderJob_RESULT_SUCCESS = 0;
  58.  
  59. int renderMovieRequest(movieRequest *movieRequestObj, string outputPath);
  60.  
  61. JNIEXPORT jint JNICALL Java_com_hlcam_video_services_RenderService_renderProject(
  62.     JNIEnv *env, jclass jclazz, jobjectArray j_resources, jobject j_soundtrack,
  63.     jstring j_destination, jstring j_edit_points, jstring j_theme,
  64.     jlong j_target_length, jint j_width, jint j_height, jint j_endroll) {
  65.  
  66.     string soundtrack_path = "";
  67.     float soundtrack_ratio = 0;
  68.     if (j_soundtrack != NULL) {
  69.         marshal_soundtrack(env, j_soundtrack, soundtrack_path, soundtrack_ratio);
  70.     }
  71.  
  72.     string dest = marshal_jstring_to_string(env, j_destination);
  73.  
  74.     string edit_points;
  75.     if (j_edit_points) {
  76.         edit_points = marshal_jstring_to_string(env, j_edit_points);
  77.     } else {
  78.         edit_points = "";
  79.     }
  80.  
  81.     int theme = marshal_jstring_to_int(env, j_theme);
  82.     int target_length = j_target_length;
  83.     int width = j_width;
  84.     int height = j_height;
  85.     int endroll = j_endroll;
  86.  
  87.     movieRequest request (height, width, endroll, theme, soundtrack_path, soundtrack_ratio, edit_points);
  88.     request.duration = target_length;
  89.  
  90.     if (!marshal_resource_array(env, request, j_resources)) {
  91.         ELOG("Failed to marshal resources for some reason.");
  92.         return com_hlcam_renderer_server_internal_RenderJob_RESULT_ERROR;
  93.     }
  94.  
  95.     int renderResult = 0;
  96.     renderResult = renderMovieRequest(&request, dest);
  97.     DLOG("Render status : %i ", renderResult);
  98.  
  99.     return renderResult;
  100. }
  101.  
  102. int64_t timeBase;
  103.  
  104. void SaveFrameLocal(AVFrame *pFrame, int width, int height, int iFrame, const char *sourceFilepath) {
  105.   FILE *pFile;
  106.   char szFilename[100];
  107.   int  y;
  108.  
  109.   // Open file
  110.   sprintf(szFilename, "%s-frame%d.ppm", sourceFilepath, iFrame);
  111.   pFile=fopen(szFilename, "wb");
  112.   if(pFile==NULL) {
  113.     ELOG("Unable to write snapshot to file");
  114.   }
  115.  
  116.   // Write header
  117.   fprintf(pFile, "P6\n%d %d\n255\n", width, height);
  118.  
  119.   // Write pixel data
  120.   for(y=0; y<height; y++)
  121.     fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
  122.  
  123.   // Close file
  124.   fclose(pFile);
  125. }
  126.  
  127. bool seek(AVFormatContext *pFormatCtx, int frameIndex){
  128.  
  129.     if(!pFormatCtx)
  130.         return false;
  131.  
  132.     int64_t seekTarget = int64_t(frameIndex) * timeBase;
  133.  
  134.     if(av_seek_frame(pFormatCtx, -1, seekTarget, AVSEEK_FLAG_ANY) < 0) {
  135.         ELOG("av_seek_frame failed.");
  136.         return false;
  137.     }
  138.  
  139.     return true;
  140.  
  141. }
  142.  
  143. void processProtobuf(movieRequest *movieRequestObj) {
  144.  GOOGLE_PROTOBUF_VERIFY_VERSION;
  145.     hlcam::communication::movie::MovieBook movie_book;
  146.  
  147.     fstream input(movieRequestObj->protoBufferName.c_str(), ios::in | ios::binary);
  148.     if(!input)
  149.     {
  150.         printf("protocol buffer file not found\n");
  151.     }
  152.     else
  153.     {
  154.         if(movie_book.ParseFromIstream(&input))
  155.         {
  156.             //get the struct out of the movie book
  157.             //const hlcam::communication::movie::HighLevelScores& high_level_scores = movie_book.high_level_scores();
  158.  
  159.             size_t correspondingIdx=0;
  160.  
  161.                 DLOG("protobuf has entries for %d videos\n", movie_book.clips_size() );
  162.  
  163.             int totalOutputMovieDuration = 0;
  164.  
  165.             //go through all clips in the movie book (all the video clips)
  166.             for(int clipIter=0; clipIter<movie_book.clips_size(); clipIter++)
  167.             {
  168.                 //advance the corresponding index to the next video clip in movieRequestObj, skipping over titles and images
  169.                 while(correspondingIdx < movieRequestObj->clips.size() && movieRequestObj->clips.at(correspondingIdx)->getClipType()!=VIDEO_CLIP)
  170.                 {
  171.                     totalOutputMovieDuration += movieRequestObj->clips.at(correspondingIdx)->duration;
  172.                     correspondingIdx++;
  173.                 }
  174.  
  175.                 //printf("video # %d was at position %d among all clips\n",clipIter,correspondingIdx);
  176.                 if (correspondingIdx < movieRequestObj->clips.size() && movieRequestObj->clips.at(correspondingIdx)->getClipType()==VIDEO_CLIP) //if there was another video in the movie and we found it
  177.                 {
  178.                     //get segments for this clip
  179.                     const hlcam::communication::movie::Clip& clipInfo = movie_book.clips(clipIter);
  180.  
  181.                     #ifdef DEBUG_PRINTING
  182.                         DLOG("there are %d segments for %s\n", clipInfo.start_size(), (dynamic_pointer_cast<videoClip>(movieRequestObj->clips.at(correspondingIdx)))->vidFileName.c_str());
  183.                     #endif
  184.  
  185.                     (dynamic_pointer_cast<videoClip>(movieRequestObj->clips.at(correspondingIdx)))->fps = clipInfo.input_video_fps();
  186.  
  187.                     //we set this to true so we know that we ONLY show this clip if it actually had segments
  188.                     (dynamic_pointer_cast<videoClip>(movieRequestObj->clips.at(correspondingIdx)))->shouldHaveSegments = true;
  189.  
  190.                     for(int segIter=0; segIter<clipInfo.start_size(); segIter++)
  191.                     {
  192.                         //set the duration/inframes accordingly
  193.                         pair<int,int> thisSeg;
  194.                         thisSeg.first = clipInfo.start(segIter);
  195.                         thisSeg.second = clipInfo.end(segIter) - clipInfo.start(segIter);
  196.  
  197. //                        if (beatTime!=-1) //if the beat has been found make sure that this clip ends at the closest beat time (4 beats per measure)
  198. //                        {
  199. //                            int tempDuration = totalOutputMovieDuration + thisSeg.second;
  200. //                            tempDuration = (tempDuration - offset)/beatTime;
  201. //                            thisSeg.second = beatTime*(tempDuration) - totalOutputMovieDuration;
  202. //                        }
  203.  
  204.                         totalOutputMovieDuration += thisSeg.second;
  205.  
  206.                         int beatTime = -1;
  207.                         #ifdef DEBUG_PRINTING
  208.                             DLOG("segment [%d,%d]\n", thisSeg.first, thisSeg.second);
  209.                         #endif
  210.                         if ( (beatTime==-1 && thisSeg.second < 72) || (beatTime!=-1 && thisSeg.second < beatTime) ) // must be 3 seconds if beat unknown, or 4 beats
  211.                         {
  212.                             #ifdef DEBUG_PRINTING
  213.                                 DLOG("a segment was only %d frames long and is being discarded\n", thisSeg.second);
  214.                             #endif
  215.                         }
  216.                         else
  217.                         {
  218.                             (dynamic_pointer_cast<videoClip>(movieRequestObj->clips.at(correspondingIdx)))->segments.push_back(thisSeg);
  219.                         }
  220.                     }
  221.                 }
  222.                 correspondingIdx++;
  223.             }
  224.         }
  225.         else
  226.         {
  227.             printf("unable to read protocol buffer file\n");
  228.         }
  229.     }
  230.  
  231.     DLOG("Finished parsing protocol buffer");
  232.  }
  233.  
  234. typedef struct OutputStream {
  235.     AVStream *st;
  236.     /* pts of the next frame that will be generated */
  237.     int64_t next_pts;
  238.     int samples_count;
  239.     AVFrame *frame;
  240.     AVFrame *tmp_frame;
  241.     float t, tincr, tincr2;
  242.     struct SwsContext *sws_ctx;
  243.     struct SwrContext *swr_ctx;
  244. } OutputStream;
  245.  
  246. static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
  247. {
  248. //    AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;
  249. //    printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
  250. //           av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
  251. //           av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
  252. //           av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
  253. //           pkt->stream_index);
  254. }
  255. static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
  256. {
  257.     /* rescale output packet timestamp values from codec to stream timebase */
  258.     av_packet_rescale_ts(pkt, *time_base, st->time_base);
  259.     pkt->stream_index = st->index;
  260.     /* Write the compressed frame to the media file. */
  261.     log_packet(fmt_ctx, pkt);
  262.     return av_interleaved_write_frame(fmt_ctx, pkt);
  263. }
  264. /* Add an output stream. */
  265. static void add_stream(OutputStream *ost, AVFormatContext *oc,
  266.                        AVCodec **codec,
  267.                        enum AVCodecID codec_id) {
  268.     AVCodecContext *c;
  269.     int i;
  270.     /* find the encoder */
  271.     *codec = avcodec_find_encoder(codec_id);
  272.     if (!(*codec)) {
  273.         ELOG("Could not find encoder for '%s'\n", avcodec_get_name(codec_id));
  274.         return;
  275.     }
  276.     ost->st = avformat_new_stream(oc, *codec);
  277.     if (!ost->st) {
  278.         ELOG("Could not allocate stream\n");
  279.         return;
  280.     }
  281.     ost->st->id = oc->nb_streams-1;
  282.     c = ost->st->codec;
  283.     switch ((*codec)->type) {
  284.     case AVMEDIA_TYPE_AUDIO:
  285.         c->sample_fmt  = (*codec)->sample_fmts ?
  286.             (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
  287.         c->bit_rate    = 64000;
  288.         c->sample_rate = 44100;
  289.         if ((*codec)->supported_samplerates) {
  290.             c->sample_rate = (*codec)->supported_samplerates[0];
  291.             for (i = 0; (*codec)->supported_samplerates[i]; i++) {
  292.                 if ((*codec)->supported_samplerates[i] == 44100)
  293.                     c->sample_rate = 44100;
  294.             }
  295.         }
  296.         c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
  297.         c->channel_layout = AV_CH_LAYOUT_STEREO;
  298.         if ((*codec)->channel_layouts) {
  299.             c->channel_layout = (*codec)->channel_layouts[0];
  300.             for (i = 0; (*codec)->channel_layouts[i]; i++) {
  301.                 if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
  302.                     c->channel_layout = AV_CH_LAYOUT_STEREO;
  303.             }
  304.         }
  305.         c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
  306.         ost->st->time_base = (AVRational){ 1, c->sample_rate };
  307.         break;
  308.     case AVMEDIA_TYPE_VIDEO:
  309.         c->codec_id = codec_id;
  310.         c->bit_rate = 400000;
  311.         /* Resolution must be a multiple of two. */
  312. //        c->width    = 352;
  313. //        c->height   = 288;
  314.         c->width    = 1280;
  315.         c->height   = 720;
  316.  
  317.         /* timebase: This is the fundamental unit of time (in seconds) in terms
  318.          * of which frame timestamps are represented. For fixed-fps content,
  319.          * timebase should be 1/framerate and timestamp increments should be
  320.          * identical to 1. */
  321.         ost->st->time_base = (AVRational){ 1, STREAM_FRAME_RATE };
  322.         c->time_base       = ost->st->time_base;
  323.         c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
  324.         c->pix_fmt       = STREAM_PIX_FMT;
  325.         if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
  326.             /* just for testing, we also add B frames */
  327.             c->max_b_frames = 2;
  328.         }
  329.         if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
  330.             /* Needed to avoid using macroblocks in which some coeffs overflow.
  331.              * This does not happen with normal video, it just happens here as
  332.              * the motion of the chroma plane does not match the luma plane. */
  333.             c->mb_decision = 2;
  334.         }
  335.     break;
  336.     default:
  337.         break;
  338.     }
  339.     /* Some formats want stream headers to be separate. */
  340.     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  341.         c->flags |= CODEC_FLAG_GLOBAL_HEADER;
  342. }
  343.  
  344. /**************************************************************/
  345. /* audio output */
  346.  
  347. void printAudioFrameInfo(const AVCodecContext* codecContext, const AVFrame* frame)
  348. {
  349.     // See the following to know what data type (unsigned char, short, float, etc) to use to access the audio data:
  350.     // http://ffmpeg.org/doxygen/trunk/samplefmt_8h.html#af9a51ca15301871723577c730b5865c5
  351.     std::cout << "Audio frame info:\n"
  352.               << "  Sample count: " << frame->nb_samples << '\n'
  353.               << "  Channel count: " << codecContext->channels << '\n'
  354.               << "  Format: " << av_get_sample_fmt_name(codecContext->sample_fmt) << '\n'
  355.               << "  Bytes per sample: " << av_get_bytes_per_sample(codecContext->sample_fmt) << '\n'
  356.               << "  Is planar? " << av_sample_fmt_is_planar(codecContext->sample_fmt) << '\n';
  357.  
  358.     DLOG( "Audio frame info: \n\tSample count: %i\n\tChannel count: %i\n\tFormat: %s\n\tBytes per sample: %i\n\tIs Planar? %i\n",
  359.                         frame->nb_samples,
  360.                         codecContext->channels,
  361.                         av_get_sample_fmt_name(codecContext->sample_fmt),
  362.                         av_get_bytes_per_sample(codecContext->sample_fmt),
  363.                         av_sample_fmt_is_planar(codecContext->sample_fmt));
  364.  
  365.  
  366.     std::cout << "frame->linesize[0] tells you the size (in bytes) of each plane\n";
  367.  
  368.     if (codecContext->channels > AV_NUM_DATA_POINTERS && av_sample_fmt_is_planar(codecContext->sample_fmt))
  369.     {
  370.         std::cout << "The audio stream (and its frames) have too many channels to fit in\n"
  371.                   << "frame->data. Therefore, to access the audio data, you need to use\n"
  372.                   << "frame->extended_data to access the audio data. It's planar, so\n"
  373.                   << "each channel is in a different element. That is:\n"
  374.                   << "  frame->extended_data[0] has the data for channel 1\n"
  375.                   << "  frame->extended_data[1] has the data for channel 2\n"
  376.                   << "  etc.\n";
  377.     }
  378.     else
  379.     {
  380.         std::cout << "Either the audio data is not planar, or there is enough room in\n"
  381.                   << "frame->data to store all the channels, so you can either use\n"
  382.                   << "frame->data or frame->extended_data to access the audio data (they\n"
  383.                   << "should just point to the same data).\n";
  384.     }
  385.  
  386.     std::cout << "If the frame is planar, each channel is in a different element.\n"
  387.               << "That is:\n"
  388.               << "  frame->data[0]/frame->extended_data[0] has the data for channel 1\n"
  389.               << "  frame->data[1]/frame->extended_data[1] has the data for channel 2\n"
  390.               << "  etc.\n";
  391.  
  392.     std::cout << "If the frame is packed (not planar), then all the data is in\n"
  393.               << "frame->data[0]/frame->extended_data[0] (kind of like how some\n"
  394.               << "image formats have RGB pixels packed together, rather than storing\n"
  395.               << " the red, green, and blue channels separately in different arrays.\n";
  396. }
  397.  
  398.  
  399. static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
  400.                                   uint64_t channel_layout,
  401.                                   int sample_rate, int nb_samples)
  402. {
  403.     AVFrame *frame = av_frame_alloc();
  404.     int ret;
  405.     if (!frame) {
  406.         fprintf(stderr, "Error allocating an audio frame\n");
  407.         exit(1);
  408.     }
  409.     frame->format = sample_fmt;
  410.     frame->channel_layout = channel_layout;
  411.     frame->sample_rate = sample_rate;
  412.     frame->nb_samples = nb_samples;
  413.     if (nb_samples) {
  414.         ret = av_frame_get_buffer(frame, 0);
  415.         if (ret < 0) {
  416.             fprintf(stderr, "Error allocating an audio buffer\n");
  417.             exit(1);
  418.         }
  419.     }
  420.     return frame;
  421. }
  422. static int open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
  423. {
  424.     AVCodecContext *c;
  425.     int nb_samples;
  426.     int ret;
  427.     AVDictionary *opt = NULL;
  428.     c = ost->st->codec;
  429.     /* open it */
  430.     av_dict_copy(&opt, opt_arg, 0);
  431.     av_dict_set(&opt, "strict", "experimental", 0);
  432.  
  433.     ret = avcodec_open2(c, codec, &opt);
  434.     av_dict_free(&opt);
  435.     if (ret < 0) {
  436.         ELOG("Could not open audio codec: [%i] %s\n", ret, av_err2str(ret));
  437.         return ret;
  438.     }
  439.     /* init signal generator */
  440.     ost->t     = 0;
  441.     ost->tincr = 2 * M_PI * 110.0 / c->sample_rate;
  442.     /* increment frequency by 110 Hz per second */
  443.     ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
  444.     if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
  445.         nb_samples = 10000;
  446.     else
  447.         nb_samples = c->frame_size;
  448.     ost->frame     = alloc_audio_frame(c->sample_fmt, c->channel_layout,
  449.                                        c->sample_rate, nb_samples);
  450.     ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout,
  451.                                        c->sample_rate, nb_samples);
  452.     /* create resampler context */
  453.         ost->swr_ctx = swr_alloc();
  454.         if (!ost->swr_ctx) {
  455.             ELOG("Could not allocate resampler context\n");
  456.             return -300;
  457.         }
  458.         /* set options */
  459.         av_opt_set_int       (ost->swr_ctx, "in_channel_count",   c->channels,       0);
  460.         av_opt_set_int       (ost->swr_ctx, "in_sample_rate",     c->sample_rate,    0);
  461.         av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt",      AV_SAMPLE_FMT_S16, 0);
  462.         av_opt_set_int       (ost->swr_ctx, "out_channel_count",  c->channels,       0);
  463.         av_opt_set_int       (ost->swr_ctx, "out_sample_rate",    c->sample_rate,    0);
  464.         av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt",     c->sample_fmt,     0);
  465.         /* initialize the resampling context */
  466.         if ((ret = swr_init(ost->swr_ctx)) < 0) {
  467.             ELOG("Failed to initialize the resampling context: %i\n", ret);
  468.             return ret;
  469.         }
  470.  
  471.         return 0;
  472. }
  473. /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
  474.  * 'nb_channels' channels. */
  475. static AVFrame *get_audio_frame(OutputStream *ost)
  476. {
  477.     AVFrame *frame = ost->tmp_frame;
  478.     int j, i, v;
  479.     int16_t *q = (int16_t*)frame->data[0];
  480.     /* check if we want to generate more frames */
  481.     if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
  482.                       STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
  483.         return NULL;
  484.     for (j = 0; j <frame->nb_samples; j++) {
  485.         v = (int)(sin(ost->t) * 10000);
  486.         for (i = 0; i < ost->st->codec->channels; i++)
  487.             *q++ = v;
  488.         ost->t     += ost->tincr;
  489.         ost->tincr += ost->tincr2;
  490.     }
  491.     frame->pts = ost->next_pts;
  492.     ost->next_pts  += frame->nb_samples;
  493.     return frame;
  494. }
  495. /*
  496.  * encode one audio frame and send it to the muxer
  497.  * return 1 when encoding is finished, 0 otherwise
  498.  */
  499. static int write_audio_frame(AVFormatContext *oc, OutputStream *ost, AVFrame *frame)
  500. {
  501.     AVCodecContext *c;
  502.     AVPacket pkt = { 0 }; // data and size must be 0;
  503. //    AVFrame *frame;
  504.     int ret;
  505.     int got_packet;
  506.     int dst_nb_samples;
  507.     av_init_packet(&pkt);
  508.     c = ost->st->codec;
  509. //    frame = get_audio_frame(ost);
  510.     if (frame) {
  511.         /* convert samples from native format to destination codec format, using the resampler */
  512.             /* compute destination number of samples */
  513.             dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
  514.                                             c->sample_rate, c->sample_rate, AV_ROUND_UP);
  515.             av_assert0(dst_nb_samples == frame->nb_samples);
  516.         /* when we pass a frame to the encoder, it may keep a reference to it
  517.          * internally;
  518.          * make sure we do not overwrite it here
  519.          */
  520.         ret = av_frame_make_writable(ost->frame);
  521.         if (ret < 0) {
  522.             ELOG("Unable to prepare frame for writing: Error code: %s", av_err2str(ret));
  523.             return ret;
  524.         }
  525.             /* convert to destination format */
  526.             ret = swr_convert(ost->swr_ctx,
  527.                               ost->frame->data, dst_nb_samples,
  528.                               (const uint8_t **)frame->data, frame->nb_samples);
  529.             if (ret < 0) {
  530.                 ELOG("Error while converting: %s\n", av_err2str(ret));
  531.                 return -1;
  532.             }
  533.             frame = ost->frame;
  534.         frame->pts = av_rescale_q(ost->samples_count, (AVRational){1, c->sample_rate}, c->time_base);
  535.         ost->samples_count += dst_nb_samples;
  536.     }
  537.     ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
  538.     if (ret < 0) {
  539.         ELOG("Error encoding audio frame: %s\n", av_err2str(ret));
  540.         return -1;
  541.     }
  542.     if (got_packet) {
  543.         ret = write_frame(oc, &c->time_base, ost->st, &pkt);
  544.         if (ret < 0) {
  545.             ELOG( "Error while writing audio frame: %s\n", av_err2str(ret));
  546.             return -1;
  547.         }
  548.     }
  549.     return (frame || got_packet) ? 0 : 1;
  550. }
  551.  
  552.  
  553. /**************************************************************/
  554. /* video output */
  555. static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
  556. {
  557.     AVFrame *picture;
  558.     int ret;
  559.     picture = av_frame_alloc();
  560.     if (!picture)
  561.         return NULL;
  562.     picture->format = pix_fmt;
  563.     picture->width  = width;
  564.     picture->height = height;
  565.     /* allocate the buffers for the frame data */
  566.     ret = av_frame_get_buffer(picture, 32);
  567.     if (ret < 0) {
  568.         fprintf(stderr, "Could not allocate frame data.\n");
  569.         exit(1);
  570.     }
  571.     return picture;
  572. }
  573.  
  574.  
  575. static int open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
  576. {
  577.     int ret;
  578.     AVCodecContext *c = ost->st->codec;
  579.     AVDictionary *opt = NULL;
  580.     av_dict_copy(&opt, opt_arg, 0);
  581.     /* open the codec */
  582.     ret = avcodec_open2(c, codec, &opt);
  583.     av_dict_free(&opt);
  584.  
  585.     if (ret < 0) {
  586.         ELOG("Could not open video codec: %s\n", av_err2str(ret));
  587.         return ret;
  588.     }
  589.     /* allocate and init a re-usable frame */
  590.     DLOG("Allocate and init a are-usable frame: %i x %i Format: %i", c->width, c->height, c->pix_fmt);
  591.     ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
  592.     if (!ost->frame) {
  593.         ELOG("Could not allocate video frame\n");
  594.         return -100;
  595.     }
  596.  
  597.     /* If the output format is not YUV420P, then a temporary YUV420P
  598.      * picture is needed too. It is then converted to the required
  599.      * output format. */
  600.     ost->tmp_frame = NULL;
  601.     if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
  602.         DLOG("input format is not YUV420P converting to size %i x %i", c->width, c->height);
  603.         ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
  604.         if (!ost->tmp_frame) {
  605.             ELOG("Could not allocate temporary picture\n");
  606.             return -200;
  607.         }
  608.     }
  609.  
  610.     return 0;
  611. }
  612.  
  613. /* Prepare a dummy image. */
  614. static void fill_yuv_image(AVFrame *pict, int frame_index,
  615.  
  616.                            int width, int height)
  617. {
  618.     int x, y, i, ret;
  619.     /* when we pass a frame to the encoder, it may keep a reference to it
  620.      * internally;
  621.      * make sure we do not overwrite it here
  622.      */
  623.     ret = av_frame_make_writable(pict);
  624.     if (ret < 0)
  625.         exit(1);
  626.     i = frame_index;
  627.     /* Y */
  628.     for (y = 0; y < height; y++)
  629.         for (x = 0; x < width; x++)
  630.             pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
  631.     /* Cb and Cr */
  632.     for (y = 0; y < height / 2; y++) {
  633.         for (x = 0; x < width / 2; x++) {
  634.             pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
  635.             pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
  636.         }
  637.     }
  638. }
  639. static AVFrame *get_video_frame(OutputStream *ost)
  640. {
  641.     AVCodecContext *c = ost->st->codec;
  642.     /* check if we want to generate more frames */
  643.     if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
  644.                       STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
  645.         return NULL;
  646.     if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
  647.         /* as we only generate a YUV420P picture, we must convert it
  648.          * to the codec pixel format if needed */
  649.         if (!ost->sws_ctx) {
  650.             ost->sws_ctx = sws_getContext(c->width, c->height,
  651.                                           AV_PIX_FMT_YUV420P,
  652.                                           c->width, c->height,
  653.                                           c->pix_fmt,
  654.                                           SCALE_FLAGS, NULL, NULL, NULL);
  655.             if (!ost->sws_ctx) {
  656.                 fprintf(stderr,
  657.                         "Could not initialize the conversion context\n");
  658.                 exit(1);
  659.             }
  660.         }
  661.         fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height);
  662.         sws_scale(ost->sws_ctx,
  663.                   (const uint8_t * const *)ost->tmp_frame->data, ost->tmp_frame->linesize,
  664.                   0, c->height, ost->frame->data, ost->frame->linesize);
  665.     } else {
  666.         fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);
  667.     }
  668.     ost->frame->pts = ost->next_pts++;
  669.     return ost->frame;
  670. }
  671. /*
  672.  * encode one video frame and send it to the muxer
  673.  * return 1 when encoding is finished, 0 otherwise
  674.  */
  675. static int write_video_frame(AVFormatContext *oc, OutputStream *ost, AVFrame *frame)
  676. {
  677.     int ret;
  678.     AVCodecContext *c;
  679. //    AVFrame *frame;
  680.     int got_packet = 0;
  681.     c = ost->st->codec;
  682. //    frame = get_video_frame(ost);
  683.     if (oc->oformat->flags & AVFMT_RAWPICTURE) {
  684.         /* a hack to avoid data copy with some raw video muxers */
  685.         AVPacket pkt;
  686.         av_init_packet(&pkt);
  687.         if (!frame)
  688.             return 1;
  689.         pkt.flags        |= AV_PKT_FLAG_KEY;
  690.         pkt.stream_index  = ost->st->index;
  691.         pkt.data          = (uint8_t *)frame;
  692.         pkt.size          = sizeof(AVPicture);
  693.         pkt.pts = pkt.dts = frame->pts;
  694.         av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base);
  695.         ret = av_interleaved_write_frame(oc, &pkt);
  696.     } else {
  697.         AVPacket pkt = { 0 };
  698.         av_init_packet(&pkt);
  699.         /* encode the image */
  700.         ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
  701.         if (ret < 0) {
  702.             ELOG("Error encoding video frame: %s\n", av_err2str(ret));
  703.             exit(1);
  704.         }
  705.         if (got_packet) {
  706.             ret = write_frame(oc, &c->time_base, ost->st, &pkt);
  707.         } else {
  708.             ret = 0;
  709.         }
  710.     }
  711.     if (ret < 0) {
  712.         ELOG("Error while writing video frame: %s\n", av_err2str(ret));
  713.         exit(1);
  714.     }
  715.     return (frame || got_packet) ? 0 : 1;
  716. }
  717. static void close_stream(AVFormatContext *oc, OutputStream *ost)
  718. {
  719.     avcodec_close(ost->st->codec);
  720.     av_frame_free(&ost->frame);
  721.     av_frame_free(&ost->tmp_frame);
  722.     sws_freeContext(ost->sws_ctx);
  723.     swr_free(&ost->swr_ctx);
  724. }
  725.  
  726.  
  727.  
  728. int renderMovieRequest(movieRequest *movieRequestObj, string outputPath) {
  729.     AVOutputFormat *ofmt = NULL;
  730.     AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
  731.     AVFormatContext *pFormatCtx = NULL;
  732.     AVCodec *audio_codec, *video_codec;
  733.  
  734.     OutputStream video_st = { 0 }, audio_st = { 0 };
  735.     size_t            i;
  736.     int             videoStream, audioStream;
  737.     AVCodecContext  *pCodecCtx = NULL;
  738.     AVCodecContext *audioCodecCtx = NULL;
  739.     AVCodec         *pCodec = NULL;
  740.     AVFrame         *aFrame = NULL;
  741.     AVFrame         *pFrame = NULL;
  742.     AVFrame         *pFrameRGB = NULL;
  743.     AVPacket        packet = { 0 };
  744.     int             frameFinished;
  745.     int             audioFrameFinished;
  746.     int             numBytes;
  747.     uint8_t         *buffer = NULL;
  748.     AVDictionary    *optionsDict = NULL;
  749.     AVDictionary *opt = NULL;
  750.     struct SwsContext      *sws_ctx = NULL;
  751.  
  752.     const char *in_filename, *out_filename;
  753.     int ret;
  754.  
  755.     int have_audio = 0, have_video = 0;
  756.     int encode_audio = 0, encode_video = 0;
  757.  
  758.     processProtobuf(movieRequestObj);
  759.  
  760.     out_filename = outputPath.c_str();
  761.  
  762.     av_register_all();
  763.  
  764.     DLOG("attempting to create context for output file %s", out_filename);
  765.  
  766.     avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
  767.     if (!ofmt_ctx) {
  768.         ELOG("Could not create output context\n");
  769.         ret = AVERROR_UNKNOWN;
  770.         return ret; //goto end;
  771.     }
  772.     ofmt = ofmt_ctx->oformat;
  773.  
  774.    /* Add the audio and video streams using the default format codecs
  775.        * and initialize the codecs. */
  776.       if (ofmt->video_codec != AV_CODEC_ID_NONE) {
  777.           add_stream(&video_st, ofmt_ctx, &video_codec, ofmt->video_codec);
  778.           have_video = 1;
  779.           encode_video = 1;
  780.       }
  781.       if (ofmt->audio_codec != AV_CODEC_ID_NONE) {
  782.           add_stream(&audio_st, ofmt_ctx, &audio_codec, ofmt->audio_codec);
  783.           have_audio = 1;
  784.           encode_audio = 1;
  785.       }
  786.  
  787.     DLOG("allocate encode buffers");
  788.  /* Now that all the parameters are set, we can open the audio and
  789.      * video codecs and allocate the necessary encode buffers. */
  790.     if (have_video)
  791.         open_video(ofmt_ctx, video_codec, &video_st, opt);
  792.     if (have_audio) {
  793.         DLOG("Opening audio codec");
  794.         open_audio(ofmt_ctx, audio_codec, &audio_st, opt);
  795.     }
  796.  
  797.     DLOG("open output file for writing");
  798.    /* open the output file, if needed */
  799.     if (!(ofmt->flags & AVFMT_NOFILE)) {
  800.         ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
  801.         if (ret < 0) {
  802.             ELOG( "Could not open '%s': %s\n", out_filename, av_err2str(ret));
  803.             return 1;
  804.         }
  805.     }
  806.  
  807.     /* Write the stream header, if any. */
  808.     ret = avformat_write_header(ofmt_ctx, &opt);
  809.     if (ret < 0) {
  810.         ELOG("Error occurred when opening output file: %s\n", av_err2str(ret));
  811.         return 1;
  812.     }
  813.  
  814.     vector<clipShPtr> * clips = &(movieRequestObj->clips);
  815.  
  816.     DLOG("ready to process clips: %i", clips->size());
  817.     for (size_t clipIdx = 0; clipIdx < clips->size(); ++clipIdx) {
  818.  
  819.         shared_ptr<clip> currentClip = clips->at(clipIdx);
  820.  
  821.         switch (currentClip->getClipType()) {
  822.             case VIDEO_CLIP: {
  823.                 shared_ptr<videoClip> vidClip = dynamic_pointer_cast<videoClip>(clips->at(clipIdx));
  824.  
  825.                 if (vidClip->shouldHaveSegments) {
  826.                     // open the file for reading and create a temporary file for output
  827.                     in_filename = vidClip->vidFileName.c_str();
  828.                     DLOG("Opening %s for reading", in_filename);
  829.  
  830.                     if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
  831.                         ELOG("Could not open input file '%s'", in_filename);
  832.                         return ret; //goto end;
  833.                     }
  834.  
  835.                     if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
  836.                         ELOG("Failed to retrieve input stream information");
  837.                         return ret; //goto end;
  838.                     }
  839.  
  840.                     av_dump_format(ifmt_ctx, 0, in_filename, 0);
  841.  
  842.                     videoStream = -1;
  843.                     audioStream = -1;
  844.                     // setup input format context and output format context;
  845. //                    AVStream *video_in_stream = NULL;
  846.                     for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  847.                         if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
  848.                             videoStream=i;
  849. //                            video_in_stream = ifmt_ctx->streams[i];
  850.                         }
  851.                         else if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO) {
  852.                             audioStream=i;
  853.                             DLOG("Found audio stream at index %i", i);
  854. //                            video_in_stream = ifmt_ctx->streams[i];
  855.                         }
  856.                     }
  857.  
  858.                     audioStream = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pCodec, 0);
  859.                     if (audioStream < 0) {
  860.                         DLOG("Could not find audio stream in file");
  861.                         avformat_close_input(&ifmt_ctx);
  862.                         continue;
  863.                     }
  864.                     if (videoStream == -1) {
  865.                         DLOG("not a video stream.");
  866.                         avformat_close_input(&ifmt_ctx);
  867.                         continue;
  868.                     }
  869.                     // Get a pointer to the codec context for the audio stream
  870.                     audioCodecCtx = ifmt_ctx->streams[audioStream]->codec;
  871.  
  872.                     // Get a pointer to the codec context for the video stream
  873.                     pCodecCtx = ifmt_ctx->streams[videoStream]->codec;
  874.  
  875.                     if (pCodecCtx == NULL) {
  876.                         ELOG("Error in getting pointer to codec for vidstream");
  877.                     }
  878.  
  879.                     if (audioCodecCtx == NULL) {
  880.                         ELOG("Error in getting pointer to codec for audio stream");
  881.                     }
  882.  
  883.                     audioCodecCtx-> codec = pCodec;
  884.  
  885.                     // Find the decoder for the video stream
  886.                     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  887.  
  888.                     if(pCodec==NULL) {
  889.                         ELOG("Unsupported codec!\n");
  890.                         return -1; // Codec not found
  891.                     }
  892.                     // Open codec
  893.                     if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0) {
  894.                         ELOG("Unable to open codec");
  895.                         return -1; // Could not open codec
  896.                     }
  897.  
  898.                     if (avcodec_open2(audioCodecCtx, audioCodecCtx->codec, NULL) != 0)
  899.                     {
  900.                         av_free(pFrame);
  901.                         avformat_close_input(&ifmt_ctx);
  902.                         ELOG("Couldn't open the context with the decoder" );
  903.                         return 1;
  904.  
  905.                     }
  906.  
  907.                     DLOG("This stream(%i) has %i channels and a sample rate of %iHz ", audioStream, audioCodecCtx->channels, audioCodecCtx->sample_rate);
  908.                     DLOG("The data is in the format %s", av_get_sample_fmt_name(audioCodecCtx->sample_fmt));
  909.  
  910.  
  911.                     // get the timebase
  912.                     timeBase = (int64_t(pCodecCtx->time_base.num) * AV_TIME_BASE) / int64_t(pCodecCtx->time_base.den);
  913.  
  914.                     // Allocate video frame
  915.                     pFrame=av_frame_alloc();
  916.  
  917.  
  918.                     // Allocate an AVFrame structure
  919.                     pFrameRGB=av_frame_alloc();
  920.                     if(pFrameRGB==NULL)
  921.                         return -1;
  922.  
  923.                     // Determine required buffer size and allocate buffer
  924. //                    numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
  925.                     numBytes = avpicture_get_size(PIX_FMT_RGB24, movieRequestObj->width, movieRequestObj->height);
  926.                     DLOG("Buffer size allocated: %i x %i: %i ", movieRequestObj->width, movieRequestObj->height, numBytes);
  927.                     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
  928.  
  929.                     sws_ctx = sws_getContext
  930.                     (
  931.                         pCodecCtx->width,
  932.                         pCodecCtx->height,
  933.                         pCodecCtx->pix_fmt,
  934.                         movieRequestObj->width,
  935.                         movieRequestObj->height,
  936.                         PIX_FMT_RGB24,
  937.                         SWS_BILINEAR,
  938.                         NULL,
  939.                         NULL,
  940.                         NULL
  941.                     );
  942.  
  943.                     // Assign appropriate parts of buffer to image planes in pFrameRGB
  944.                     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
  945.                     // of AVPicture
  946.                     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, movieRequestObj->width, movieRequestObj->height);
  947.                     size_t numSegments = vidClip->segments.size();
  948.  
  949.                     DLOG("Found %i segments to process", numSegments);
  950.                     for (size_t segmentIdx = 0; segmentIdx < numSegments; ++segmentIdx) {
  951.                         // seek to the right position
  952.                         int frameOffset = vidClip->segments.at(segmentIdx).first;
  953.                         int clipDuration = vidClip->segments.at(segmentIdx).second;
  954.                         DLOG("Starting Frame Number: %i Duration: %i", frameOffset, clipDuration);
  955.  
  956.                         seek(ifmt_ctx, frameOffset);
  957.                         // loop for X frames where X is < frameOffset + clipDuration; clipDuration is the length of the clip in terms of frames
  958.                         for (int frameIdx = frameOffset; frameIdx < (frameOffset + clipDuration); ++frameIdx) {
  959.                             av_init_packet(&packet);
  960.                             int avReadResult = 0;
  961.                             int continueRecording = 1;
  962.                             while ((continueRecording == 1) && (frameIdx < (frameOffset + clipDuration) )) {
  963.                                 avReadResult = av_read_frame(ifmt_ctx, &packet);
  964.                                 if(avReadResult != 0){
  965.                                     if (avReadResult != AVERROR_EOF) {
  966.                                         ELOG("av_read_frame error: %i", avReadResult );
  967.                                     } else {
  968.                                         ILOG("End of input file");
  969.                                     }
  970.                                     continueRecording = 0;
  971.                                 }
  972.                                 // Is this a packet from the video stream?
  973.                                 if(packet.stream_index==videoStream) {
  974.                                     // Decode video frame
  975.                                     avcodec_decode_video2(pCodecCtx, pFrameRGB, &frameFinished, &packet);
  976.  
  977.                                     // Did we get a video frame?
  978.                                     if(frameFinished) {
  979.                                         // Convert the image from its native format to RGB
  980.                                         sws_scale
  981.                                         (
  982.                                            sws_ctx,
  983.                                            (uint8_t const * const *)pFrame->data,
  984.                                            pFrame->linesize,
  985.                                            0,
  986.                                            pCodecCtx->height,
  987.                                            pFrameRGB->data,
  988.                                            pFrameRGB->linesize
  989.                                         );
  990.                                         write_video_frame(ofmt_ctx, &video_st, pFrameRGB);
  991.                                         frameIdx++;
  992.                                     }
  993.  
  994.                                 }
  995.                                 else if (packet.stream_index == audioStream) {
  996. //                                    // Decode audio frame
  997. //                                    int audioErr = avcodec_decode_audio4(pCodecCtx, pFrameRGB, &audioFrameFinished, &packet);
  998. //
  999. //                                    DLOG("Audio frame decoded.  decode status: [%i] %s", audioErr, av_err2str(audioErr));
  1000. //                                    if (audioFrameFinished) {
  1001. ////                                        write the audio frame to file
  1002. //                                        write_audio_frame(ofmt_ctx, &audio_st, pFrameRGB);
  1003. //
  1004. //                                    }
  1005.  
  1006.                                     AVPacket decodingPacket = packet;
  1007.  
  1008.                                     // Audio packets can have multiple audio frames in a single packet
  1009.                                     while (decodingPacket.size > 0)
  1010.                                     {
  1011.                                         // Try to decode the packet into a frame
  1012.                                         // Some frames rely on multiple packets, so we have to make sure the frame is finished before
  1013.                                         // we can use it
  1014.                                         int gotFrame = 0;
  1015.                                         if (!aFrame) {
  1016.                                             if (!(aFrame = av_frame_alloc())) {
  1017.                                                 fprintf(stderr, "Could not allocate audio frame\n");
  1018.                                                 exit(1);
  1019.                                             }
  1020.                                         }
  1021.                                         int result = avcodec_decode_audio4(audioCodecCtx, aFrame, &gotFrame, &decodingPacket);
  1022.                                         DLOG("Audio frame decoded.  decode status: [%i] %s", result, av_err2str(result));
  1023.  
  1024.                                         if (result >= 0 && gotFrame)
  1025.                                         {
  1026.                                             decodingPacket.size -= result;
  1027.                                             decodingPacket.data += result;
  1028.  
  1029.                                             // We now have a fully decoded audio frame
  1030.                                             printAudioFrameInfo(audioCodecCtx, pFrameRGB);
  1031.                                             write_audio_frame(ofmt_ctx, &audio_st, pFrameRGB);
  1032.                                         }
  1033.                                         else
  1034.                                         {
  1035.                                             decodingPacket.size = 0;
  1036.                                             decodingPacket.data = nullptr;
  1037.                                         }
  1038.                                     }
  1039.  
  1040.                                 }
  1041.                                 // Free the packet that was allocated by av_read_frame
  1042.                                 av_free_packet(&packet);
  1043.                             }
  1044.                                 // Free the RGB image
  1045.  
  1046.                         }
  1047.                     }
  1048.  
  1049.                     DLOG("Cleaning up frame allocations");
  1050.                     av_free(buffer);
  1051.                     av_free(pFrameRGB);
  1052.                     av_free(aFrame);
  1053.                     // Free the YUV frame
  1054.                     av_free(pFrame);
  1055.  
  1056.                 } // end video clip processing
  1057.             }
  1058.             break;
  1059.  
  1060.             case TITLE_CLIP: {
  1061.               }
  1062.             break;
  1063.  
  1064.             default:
  1065.                 ELOG("Failed to identify clip");
  1066.                 break;
  1067.         } // end switch statement
  1068.  
  1069.         DLOG("Finished processing clip #%i", clipIdx);
  1070.         avformat_close_input(&ifmt_ctx);
  1071.     } // end main for loop -> clip iteration
  1072.  
  1073.  
  1074.  /* Write the trailer, if any. The trailer must be written before you
  1075.      * close the CodecContexts open when you wrote the header; otherwise
  1076.      * av_write_trailer() may try to use memory that was freed on
  1077.      * av_codec_close(). */
  1078.     av_write_trailer(ofmt_ctx);
  1079.  
  1080.     /* Close each codec. */
  1081.     if (have_video)
  1082.         close_stream(ofmt_ctx, &video_st);
  1083.     if (have_audio)
  1084.         close_stream(ofmt_ctx, &audio_st);
  1085.  
  1086.     if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) {
  1087.         /* Close the output file. */
  1088.         avio_close(ofmt_ctx->pb);
  1089.     }
  1090.  
  1091.     DLOG("Closing input format context");
  1092.     avformat_close_input(&ifmt_ctx);
  1093.  
  1094.     DLOG("Free ouptut format context");
  1095.     avformat_free_context(ofmt_ctx);
  1096.  
  1097.     if (ret < 0 && ret != AVERROR_EOF) {
  1098.         ELOG( "Error occurred: %s\n", av_err2str(ret));
  1099.         return 1;
  1100.     }
  1101.  
  1102.     return 0;
  1103. }
  1104.  
  1105.  
  1106.  
  1107.  
  1108. // marshal routines transform jobj to c/c++ type
  1109. static bool marshal_resource_array(JNIEnv *env, movieRequest &request, jobjectArray j_resources) {
  1110.   jsize j_length = env->GetArrayLength(j_resources);
  1111.  
  1112.   vector<clip *> v;
  1113.  
  1114.   for (jsize i = 0; i < j_length; i++) {
  1115.     clip * c = marshal_resource_to_clip(env, env->GetObjectArrayElement(j_resources, i));
  1116.     if (c == NULL) {
  1117.       return false;
  1118.     }
  1119.     request.push_back(*c);
  1120.   }
  1121.  
  1122.   return true;
  1123. }
  1124.  
  1125. static clip * marshal_resource_to_clip(JNIEnv * env, const jobject &j_resource) {
  1126.   // Get Resource type
  1127.   // This resource is either a title, photo, or video
  1128.   jclass j_cls = env->GetObjectClass(j_resource);
  1129.   jmethodID j_mid = env->GetMethodID(j_cls, "getMimeType", "()Ljava/lang/String;");
  1130.   jstring j_mime_type = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1131.  
  1132.   string mimeType = marshal_jstring_to_string(env, j_mime_type);
  1133.  
  1134.   if (mimeType.find("video/") == 0) {
  1135.     return marshal_video(env, j_resource);
  1136.   } else if (mimeType.find("image/") == 0) {
  1137.     return marshal_image(env, j_resource);
  1138.   } else if (mimeType.find("audio/") == 0) {
  1139.     return marshal_audio(env, j_resource);
  1140.   } else if (mimeType.find("text/") == 0) {
  1141.     return marshal_text(env, j_resource);
  1142.   } else if (mimeType.find("application/slide") == 0) {
  1143.     return marshal_text(env, j_resource);
  1144.   } else {
  1145.     std::cout << "Invalid mimetype '" << mimeType << "'" << std::endl;
  1146.     return NULL;
  1147.   }
  1148. }
  1149.  
  1150. static clip * marshal_video(JNIEnv *env, const jobject &j_resource) {
  1151.   videoClip * c = new videoClip();
  1152.  
  1153.   jclass j_cls = env->GetObjectClass(j_resource);
  1154.   jmethodID j_mid = env->GetMethodID(j_cls, "getAssetUri", "()Ljava/lang/String;");
  1155.   jstring j_uri = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1156.   c->vidFileName = marshal_jstring_to_string(env, j_uri);
  1157.  
  1158. //  j_mid = env->GetMethodID(j_cls, "getRotationAngle", "()I");
  1159.   c->rotationAngle = 0; //env->CallIntMethod(j_resource, j_mid);
  1160.  
  1161.   j_mid = env->GetMethodID(j_cls, "getCaptionText", "()Ljava/lang/String;");
  1162.   jstring j_caption = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1163.  
  1164.   c->captionText = marshal_jstring_to_string(env, j_caption);
  1165.  
  1166. //  j_mid = env->GetMethodID(j_cls, "getCaptionColor", "()Ljava/awt/Color;");
  1167. //  jobject j_caption_color = env->CallObjectMethod(j_resource, j_mid);
  1168.   float captionR = 255.0, captionG = 255.0, captionB = 255.0;
  1169. //  marshal_color(env, j_caption_color, captionR, captionG, captionB);
  1170.   if ( captionR >= 0)
  1171.     c->captionR = captionR;
  1172.   if (captionG >= 0)
  1173.     c->captionG = captionG;
  1174.   if (captionB >= 0)
  1175.     c->captionB = captionB;
  1176.  
  1177.     DLOG("Add Video: [ vidFilename: %s\ncaptionText: %s", c->vidFileName.c_str(), c->captionText.c_str());
  1178.   std::cout << "Add Video[";
  1179.   std::cout << " vidFileName: " << c->vidFileName;
  1180.   std::cout << " rotationAngle: " << c->rotationAngle;
  1181.   std::cout << " captionText: " << c->captionText;
  1182.   std::cout << " captionR: " << c->captionR;
  1183.   std::cout << " captionG: " << c->captionG;
  1184.   std::cout << " captionB: " << c->captionB;
  1185.   std::cout << "]" << std::endl;
  1186.   return c;
  1187. }
  1188.  
  1189. static clip * marshal_image(JNIEnv *env, const jobject &j_resource) {
  1190.   imageClip * c = new imageClip();
  1191.  
  1192.   jclass j_cls = env->GetObjectClass(j_resource);
  1193.  
  1194.   jmethodID j_mid = env->GetMethodID(j_cls, "getAssetUri",
  1195.                                      "()Ljava/lang/String;");
  1196.   jstring j_uri = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1197.   c->imgFileName = marshal_jstring_to_string(env, j_uri);
  1198.  
  1199. //  j_mid = env->GetMethodID(j_cls, "getRotationAngle", "()I");
  1200.   c->rotationAngle = 0; //env->CallIntMethod(j_resource, j_mid);
  1201.  
  1202.   j_mid = env->GetMethodID(j_cls, "getCaption", "()Ljava/lang/String;");
  1203.   jstring j_caption = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1204.   c->captionText = marshal_jstring_to_string(env, j_caption);
  1205.  
  1206. //  j_mid = env->GetMethodID(j_cls, "getCaptionColor", "()Ljava/awt/Color;");
  1207. //  jobject j_caption_color = env->CallObjectMethod(j_resource, j_mid);
  1208.   float captionR = 255, captionG = 255, captionB = 255;
  1209. //  marshal_color(env, j_caption_color, captionR,captionG, captionB);
  1210.   if ( captionR >= 0)
  1211.     c->captionR = captionR;
  1212.   if (captionG >= 0)
  1213.     c->captionG = captionG;
  1214.   if (captionB >= 0)
  1215.     c->captionB = captionB;
  1216.  
  1217.   std::cout << "Add Image[";
  1218.   std::cout << " imgFileName: " << c->imgFileName;
  1219.   std::cout << " rotationAngle: " << c->rotationAngle;
  1220.   std::cout << " captionText: " << c->captionText;
  1221.   std::cout << " captionR: " << c->captionR;
  1222.   std::cout << " captionG: " << c->captionG;
  1223.   std::cout << " captionB: " << c->captionB;
  1224.   std::cout << "]" << std::endl;
  1225.  
  1226.   return c;
  1227. }
  1228.  
  1229. static clip * marshal_text(JNIEnv *env, const jobject &j_resource) {
  1230.   titleClip * c = new titleClip();
  1231.  
  1232.   jclass j_cls = env->GetObjectClass(j_resource);
  1233.  
  1234.   jmethodID j_mid = env->GetMethodID(j_cls, "getCaption", "()Ljava/lang/String;");
  1235.   jstring j_caption = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1236.   c->captionText = marshal_jstring_to_string(env, j_caption);
  1237.  
  1238. //  j_mid = env->GetMethodID(j_cls, "getCaptionColor", "()Ljava/awt/Color;");
  1239. //  jobject j_caption_color = env->CallObjectMethod(j_resource, j_mid);
  1240.   float captionR = 255.0, captionG = 255.0, captionB = 255.0;
  1241. //  marshal_color(env, j_caption_color, captionR, captionG, captionB);
  1242.   if (captionR >= 0 )
  1243.     c->captionR = captionR;
  1244.   if (captionG >= 0)
  1245.     c->captionG = captionG;
  1246.   if (captionB >= 0)
  1247.     c->captionB = captionB;
  1248.  
  1249.   j_mid = env->GetMethodID(j_cls, "getText", "()Ljava/lang/String;");
  1250.   jstring jtext = (jstring) env->CallObjectMethod(j_resource, j_mid);
  1251.   c->titleText = marshal_jstring_to_string(env, jtext);
  1252.  
  1253. //  j_mid = env->GetMethodID(j_cls, "getForeground", "()Ljava/awt/Color;");
  1254. //  jobject j_foreground = env->CallObjectMethod(j_resource, j_mid);
  1255.   float textR = 255.0, textG = 255.0, textB = 255.0;
  1256. //  marshal_color(env, j_foreground, textR, textG, textB);
  1257.   if (textR >= 0)
  1258.       c->textR = textR;
  1259.   if (textG >= 0)
  1260.       c->textG = textG;
  1261.   if (textB >= 0)
  1262.       c->textB = textB;
  1263.  
  1264. //  j_mid = env->GetMethodID(j_cls, "getBackground", "()Ljava/awt/Color;");
  1265. //  jobject j_background = env->CallObjectMethod(j_resource, j_mid);
  1266.   float backgroundR = 125.0, backgroundG = 125.0, backgroundB = 125.0;
  1267. //  marshal_color(env, j_background, backgroundR, backgroundG, backgroundB);
  1268.   if (backgroundR >= 0)
  1269.       c->backgroundR = backgroundR;
  1270.   if (backgroundG >= 0)
  1271.       c->backgroundG = backgroundG;
  1272.   if (backgroundB >= 0)
  1273.       c->backgroundB = backgroundB;
  1274.  
  1275.   std::cout << "Add Text[";
  1276.   std::cout << " captionText: " << c->captionText;
  1277.   std::cout << " captionR: " << c->captionR;
  1278.   std::cout << " captionG: " << c->captionG;
  1279.   std::cout << " captionB: " << c->captionB;
  1280.   std::cout << " titleText: " << c->titleText;
  1281.   std::cout << " textR: " << c->textR;
  1282.   std::cout << " textG: " << c->textG;
  1283.   std::cout << " textB: " << c->textB;
  1284.   std::cout << " backgroundR: " << c->backgroundR;
  1285.   std::cout << " backgroundG: " << c->backgroundG;
  1286.   std::cout << " backgroundB: " << c->backgroundB;
  1287.   std::cout << "]" << std::endl;
  1288.   return c;
  1289. }
  1290.  
  1291. static clip * marshal_audio(JNIEnv *env, const jobject &j_resource) {
  1292.   // Not currently supported
  1293.   std::cout << "Audio not supported mimetype for resource" << std::endl;
  1294.   return NULL;
  1295. }
  1296.  
  1297. static void marshal_soundtrack(JNIEnv *env, const jobject &j_soundtrack,
  1298.                                string &soundtrack_path, float &ratio) {
  1299.   jclass j_cls = env->GetObjectClass(j_soundtrack);
  1300.  
  1301.   jmethodID j_mid = env->GetMethodID(j_cls, "getURI",
  1302.                                      "()Ljava/lang/String;");
  1303.   jstring j_uri = (jstring) env->CallObjectMethod(j_soundtrack, j_mid);
  1304.   soundtrack_path = marshal_jstring_to_string(env, j_uri);
  1305.  
  1306.   j_mid = env->GetMethodID(j_cls, "getRatio", "()F");
  1307.   ratio = env->CallFloatMethod(j_soundtrack, j_mid);
  1308. }
  1309.  
  1310. static string  marshal_jstring_to_string(JNIEnv *env, const jstring &j_str) {
  1311.   if (!j_str) {
  1312.     return "";
  1313.   }
  1314.  
  1315.   const char * chars = env->GetStringUTFChars(j_str, NULL);
  1316.  
  1317.   string result(chars);
  1318.  
  1319.   env->ReleaseStringUTFChars(j_str, chars);
  1320.  
  1321.   return result;
  1322. }
  1323.  
  1324. static int  marshal_jstring_to_int(JNIEnv *env, const jstring &j_str) {
  1325.   if (!j_str) {
  1326.     return 0; // we want to make sure invalid inputs default to 0
  1327.   }
  1328.  
  1329.   const char * chars = env->GetStringUTFChars(j_str, NULL);
  1330.  
  1331.   int result = atoi(chars);
  1332.  
  1333.   env->ReleaseStringUTFChars(j_str, chars);
  1334.  
  1335.   return result;
  1336. }
  1337. //
  1338. //static void marshal_color(JNIEnv *env, const jobject &j_color, float &r, float &g, float &b) {
  1339. //  if (j_color == NULL) {
  1340. //    r = g = b = -1;
  1341. //    return;
  1342. //  }
  1343. //
  1344. //  jclass j_cls = env->GetObjectClass(j_color);
  1345. //  jmethodID j_mid = env->GetMethodID(j_cls, "getRed", "()I");
  1346. //  r = ((float) env->CallIntMethod(j_color, j_mid)) / 255.0;
  1347. //  j_mid = env->GetMethodID(j_cls, "getGreen", "()I");
  1348. //  g = ((float) env->CallIntMethod(j_color, j_mid)) / 255.0;
  1349. //  j_mid = env->GetMethodID(j_cls, "getBlue", "()I");
  1350. //  b = ((float) env->CallIntMethod(j_color, j_mid)) / 255.0;
  1351. //}
  1352.  
  1353.  
  1354.  
  1355. #ifdef __cplusplus
  1356. }
  1357.  
  1358. #endif
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×