Advertisement
mnguyen

trouble with merging audio

Sep 13th, 2014
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 53.51 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement