Advertisement
mnguyen

remuxing files

Sep 10th, 2014
280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.99 KB | None | 0 0
  1. /*
  2.  * encode one video frame and send it to the muxer
  3.  * return 1 when encoding is finished, 0 otherwise
  4.  */
  5. static int write_video_frame(AVFormatContext *oc, OutputStream *ost, AVFrame *frame)
  6. {
  7.     int ret;
  8.     AVCodecContext *c;
  9. //    AVFrame *frame;
  10.     int got_packet = 0;
  11.     c = ost->st->codec;
  12. //    frame = get_video_frame(ost);
  13.     if (oc->oformat->flags & AVFMT_RAWPICTURE) {
  14.         /* a hack to avoid data copy with some raw video muxers */
  15.         AVPacket pkt;
  16.         av_init_packet(&pkt);
  17.         if (!frame)
  18.             return 1;
  19.         pkt.flags        |= AV_PKT_FLAG_KEY;
  20.         pkt.stream_index  = ost->st->index;
  21.         pkt.data          = (uint8_t *)frame;
  22.         pkt.size          = sizeof(AVPicture);
  23.         pkt.pts = pkt.dts = frame->pts;
  24.         av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base);
  25.         ret = av_interleaved_write_frame(oc, &pkt);
  26.     } else {
  27.         AVPacket pkt = { 0 };
  28.         av_init_packet(&pkt);
  29.         /* encode the image */
  30.         ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
  31.         if (ret < 0) {
  32.             fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
  33.             exit(1);
  34.         }
  35.         if (got_packet) {
  36.             ret = write_frame(oc, &c->time_base, ost->st, &pkt);
  37.         } else {
  38.             ret = 0;
  39.         }
  40.     }
  41.     if (ret < 0) {
  42.         fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
  43.         exit(1);
  44.     }
  45.     return (frame || got_packet) ? 0 : 1;
  46. }
  47. static void close_stream(AVFormatContext *oc, OutputStream *ost)
  48. {
  49.     avcodec_close(ost->st->codec);
  50.     av_frame_free(&ost->frame);
  51.     av_frame_free(&ost->tmp_frame);
  52.     sws_freeContext(ost->sws_ctx);
  53.     swr_free(&ost->swr_ctx);
  54. }
  55.  
  56.  
  57.  
  58. int renderMovieRequest(movieRequest *movieRequestObj, string outputPath) {
  59.     AVOutputFormat *ofmt = NULL;
  60.     AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
  61.     AVFormatContext *pFormatCtx = NULL;
  62.     AVCodec *audio_codec, *video_codec;
  63.  
  64.     OutputStream video_st = { 0 }, audio_st = { 0 };
  65.     size_t            i;
  66.     int             videoStream;
  67.     AVCodecContext  *pCodecCtx = NULL;
  68.     AVCodec         *pCodec = NULL;
  69.     AVFrame         *pFrame = NULL;
  70.     AVFrame         *pFrameRGB = NULL;
  71.     AVPacket        packet = { 0 };
  72.     int             frameFinished;
  73.     int             numBytes;
  74.     uint8_t         *buffer = NULL;
  75.     AVDictionary    *optionsDict = NULL;
  76.     AVDictionary *opt = NULL;
  77.     struct SwsContext      *sws_ctx = NULL;
  78.  
  79.     const char *in_filename, *out_filename;
  80.     int ret;
  81.  
  82.     int have_audio = 0, have_video = 0;
  83.     int encode_audio = 0, encode_video = 0;
  84.  
  85.     processProtobuf(movieRequestObj);
  86.  
  87. //    in_filename  = argv[1];
  88.     out_filename = outputPath.c_str();
  89.  
  90.     av_register_all();
  91.  
  92.     DLOG("attempting to create context for output file %s", out_filename);
  93.  
  94.     avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
  95.     if (!ofmt_ctx) {
  96.         ELOG("Could not create output context\n");
  97.         ret = AVERROR_UNKNOWN;
  98.         return ret; //goto end;
  99.     }
  100.     ofmt = ofmt_ctx->oformat;
  101.  
  102.    /* Add the audio and video streams using the default format codecs
  103.        * and initialize the codecs. */
  104.       if (ofmt->video_codec != AV_CODEC_ID_NONE) {
  105.           add_stream(&video_st, ofmt_ctx, &video_codec, ofmt->video_codec);
  106.           have_video = 1;
  107.           encode_video = 1;
  108.       }
  109.       if (ofmt->audio_codec != AV_CODEC_ID_NONE) {
  110.           add_stream(&audio_st, ofmt_ctx, &audio_codec, ofmt->audio_codec);
  111.           have_audio = 1;
  112.           encode_audio = 1;
  113.       }
  114.  
  115.     DLOG("allocate encode buffers");
  116.  /* Now that all the parameters are set, we can open the audio and
  117.      * video codecs and allocate the necessary encode buffers. */
  118.     if (have_video)
  119.         open_video(ofmt_ctx, video_codec, &video_st, opt);
  120.     if (have_audio)
  121.         open_audio(ofmt_ctx, audio_codec, &audio_st, opt);
  122.  
  123.     DLOG("open output file for writing");
  124.    /* open the output file, if needed */
  125.     if (!(ofmt->flags & AVFMT_NOFILE)) {
  126.         ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
  127.         if (ret < 0) {
  128.             ELOG( "Could not open '%s': %s\n", out_filename, av_err2str(ret));
  129.             return 1;
  130.         }
  131.     }
  132.  
  133.     /* Write the stream header, if any. */
  134.     ret = avformat_write_header(ofmt_ctx, &opt);
  135.     if (ret < 0) {
  136.         ELOG("Error occurred when opening output file: %s\n", av_err2str(ret));
  137.         return 1;
  138.     }
  139.  
  140.     vector<clipShPtr> * clips = &(movieRequestObj->clips);
  141.  
  142.     DLOG("ready to process clips: %i", clips->size());
  143.     for (size_t clipIdx = 0; clipIdx < clips->size(); ++clipIdx) {
  144.  
  145.         shared_ptr<clip> currentClip = clips->at(clipIdx);
  146.         DLOG("Processing clip %i [%s]", clipIdx, in_filename);
  147.  
  148.         switch (currentClip->getClipType()) {
  149.             case VIDEO_CLIP: {
  150.                 DLOG("clip is a video clip...");
  151.  
  152.                 shared_ptr<videoClip> vidClip = dynamic_pointer_cast<videoClip>(clips->at(clipIdx));
  153.  
  154.                 if (vidClip->shouldHaveSegments) {
  155.                     DLOG("Found segments... :");
  156.                     // add clips to new video
  157.                     // open the file for reading and create a temporary file for output
  158.                     in_filename = vidClip->vidFileName.c_str();
  159.  
  160.                     if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
  161.                         ELOG("Could not open input file '%s'", in_filename);
  162.                         return ret; //goto end;
  163.                     }
  164.  
  165.                     if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
  166.                         ELOG("Failed to retrieve input stream information");
  167.                         return ret; //goto end;
  168.                     }
  169.                     av_dump_format(ifmt_ctx, 0, in_filename, 0);
  170.  
  171.                     videoStream = -1;
  172.                     // setup input format context and output format context;
  173.                     AVStream *in_stream = NULL;
  174.                     for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  175.                         if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
  176.                             videoStream=i;
  177.                             in_stream = ifmt_ctx->streams[i];
  178.                         }
  179.                     }
  180.  
  181.                     if (videoStream == -1) {
  182.                         DLOG("not a video stream.");
  183.                         continue;
  184.                     }
  185.                     // Get a pointer to the codec context for the video stream
  186.                     pCodecCtx = ifmt_ctx->streams[videoStream]->codec;
  187.                     // Find the decoder for the video stream
  188.                     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  189.  
  190.                     if(pCodec==NULL) {
  191.                         ELOG("Unsupported codec!\n");
  192.                         return -1; // Codec not found
  193.                     }
  194.                     // Open codec
  195.                     if(avcodec_open2(pCodecCtx, pCodec, &optionsDict)<0) {
  196.                         ELOG("Unable to open codec");
  197.                         return -1; // Could not open codec
  198.                     }
  199.  
  200.                     // get the timebase
  201.                     timeBase = (int64_t(pCodecCtx->time_base.num) * AV_TIME_BASE) / int64_t(pCodecCtx->time_base.den);
  202.  
  203.                     // Allocate video frame
  204.                     pFrame=av_frame_alloc();
  205.  
  206.                     // Allocate an AVFrame structure
  207.                     pFrameRGB=av_frame_alloc();
  208.                     if(pFrameRGB==NULL)
  209.                         return -1;
  210.                     // Determine required buffer size and allocate buffer
  211.                     numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
  212.  
  213.                     DLOG("Buffer size allocated: %i x %i: %i ", pCodecCtx->width, pCodecCtx->height, numBytes);
  214.                     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
  215.  
  216.                     sws_ctx = sws_getContext
  217.                     (
  218.                         pCodecCtx->width,
  219.                         pCodecCtx->height,
  220.                         pCodecCtx->pix_fmt,
  221.                         pCodecCtx->width,
  222.                         pCodecCtx->height,
  223.                         PIX_FMT_RGB24,
  224.                         SWS_BILINEAR,
  225.                         NULL,
  226.                         NULL,
  227.                         NULL
  228.                     );
  229.  
  230.  
  231.                     // Assign appropriate parts of buffer to image planes in pFrameRGB
  232.                     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
  233.                     // of AVPicture
  234.                     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
  235.                     size_t numSegments = vidClip->segments.size();
  236.  
  237.                     DLOG("Found %i segments to process", numSegments);
  238.                     for (size_t segmentIdx = 0; segmentIdx < numSegments; ++segmentIdx) {
  239.                         // seek to the right position
  240.                         DLOG("Processing segment # %i", segmentIdx);
  241.                         int frameOffset = vidClip->segments.at(segmentIdx).first;
  242.                         int clipDuration = vidClip->segments.at(segmentIdx).second;
  243.                         DLOG("Starting Frame Number: %i", frameOffset);
  244.                         DLOG("Segment duration: %i", clipDuration);
  245.  
  246.                         seek(ifmt_ctx, frameOffset);
  247.                         // loop for X frames where X is < frameOffset + clipDuration
  248.                         for (int frameIdx = frameOffset; frameIdx < (frameOffset + clipDuration); ++frameIdx) {
  249.                             DLOG("reading in frame %i", frameIdx);
  250.                             av_init_packet(&packet);
  251.                             int avReadResult = 0;
  252.                             int continueRecording = 1;
  253.                             while(continueRecording == 1) {
  254.                                 avReadResult = av_read_frame(ifmt_ctx, &packet);
  255.                                 if(avReadResult != 0){
  256.                                     if (avReadResult != AVERROR_EOF) {
  257.                                         ELOG("av_read_frame error: %i", avReadResult );
  258.                                     } else {
  259.                                         ILOG("End of input file");
  260.                                     }
  261.                                     continueRecording = 0;
  262.                                 }
  263.                                 // Is this a packet from the video stream?
  264.                                 if(packet.stream_index==videoStream) {
  265.                                     // Decode video frame
  266.                                     avcodec_decode_video2(pCodecCtx, pFrameRGB, &frameFinished, &packet);
  267.  
  268.                                     // Did we get a video frame?
  269.                                     if(frameFinished) {
  270. //                                        // Convert the image from its native format to RGB
  271. //                                        sws_scale
  272. //                                        (
  273. //                                           sws_ctx,
  274. //                                           (uint8_t const * const *)pFrame->data,
  275. //                                           pFrame->linesize,
  276. //                                           0,
  277. //                                           pCodecCtx->height,
  278. //                                           pFrameRGB->data,
  279. //                                           pFrameRGB->linesize
  280. //                                        );
  281.  
  282.  
  283.                                         // Save the frame to disk
  284. //                                        if(frameIdx % 10 == 0) {
  285. //                                            SaveFrameLocal(pFrameRGB, pCodecCtx->width, pCodecCtx->height, frameIdx, vidClip->vidFileName.c_str());
  286. //                                        }
  287.                                         write_video_frame(ofmt_ctx, &video_st, pFrameRGB);
  288.                                         frameIdx++;
  289.                                     }
  290.                                 }
  291.                                 else {
  292.                                     // this is an audio frame.
  293.  
  294.                                 }
  295.                                 // Free the packet that was allocated by av_read_frame
  296.                                 av_free_packet(&packet);
  297.                             }
  298.                                 // Free the RGB image
  299.  
  300.                             DLOG("Cleaning up frame allocations");
  301.                             av_free(buffer);
  302.                             av_free(pFrameRGB);
  303.                             // Free the YUV frame
  304.                             av_free(pFrame);
  305.                         }
  306.                     }
  307.                 } // end video clip processing
  308.             }
  309.             break;
  310.  
  311.             case TITLE_CLIP: {
  312.               }
  313.             break;
  314.  
  315.             default:
  316.                 ELOG("Failed to identify clip");
  317.                 break;
  318.         } // end switch statement
  319.  
  320.     } // end main for loop -> clip iteration
  321.  
  322.  
  323.  /* Write the trailer, if any. The trailer must be written before you
  324.      * close the CodecContexts open when you wrote the header; otherwise
  325.      * av_write_trailer() may try to use memory that was freed on
  326.      * av_codec_close(). */
  327.     av_write_trailer(ofmt_ctx);
  328.  
  329.     /* Close each codec. */
  330.     if (have_video)
  331.         close_stream(ofmt_ctx, &video_st);
  332.     if (have_audio)
  333.         close_stream(ofmt_ctx, &audio_st);
  334.  
  335.     if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) {
  336.         /* Close the output file. */
  337.         avio_close(ofmt_ctx->pb);
  338.     }
  339.  
  340.     DLOG("Closing input format context");
  341.     avformat_close_input(&ifmt_ctx);
  342.  
  343.     DLOG("Free ouptut format context");
  344.     avformat_free_context(ofmt_ctx);
  345.  
  346.     if (ret < 0 && ret != AVERROR_EOF) {
  347.         ELOG( "Error occurred: %s\n", av_err2str(ret));
  348.         return 1;
  349.     }
  350.  
  351.     return 0;
  352. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement