Beispiel #1
0
int main(int argc, char *argv[])
{
    // Parse the options

    int opt;
    while ((opt = getopt(argc, argv, "")) != -1)
    {
        switch (opt)
        {
        default:
            usage(argv[0]);
        }
    }

    if (argc < optind+2) usage(argv[0]);

    char* file_in = argv[optind];
    char* file_out = argv[argc-1];

    // Init all the crap

    av_register_all();

    // Open the input file and get the input format context

    InputFormatContext inFormatCtx(file_in);

    dump_format(inFormatCtx.get(), 0, file_in, 0); // Just for debugging

    // Find the input video stream

    Stream inStream = inFormatCtx.GetVideoStream();

    // Get the input codec context

    CodecContext inCodecCtx = inStream.GetCodecContext();

    // Allocate the output format context, guess the format, set no parameters

    OutputFormat outFormat;

    try {
        outFormat = OutputFormat(0, file_out);
    } catch(std::runtime_error e) {
        warn("Could not guess the format based on extension, trying the input format");
        outFormat = OutputFormat(inFormatCtx.GetFormat().GetName(), file_in);
    }

    OutputFormatContext outFormatCtx(file_out, outFormat);

    // Create the output video stream

    Stream outStream = outFormatCtx.AddVideoStream();

    outStream.SetFrameRate(inStream.GetFrameRate());
    outStream.SetAspectRatio(inStream.GetAspectRatio());

    // Set the output codec context

    CodecContext outCodecCtx = outStream.GetCodecContext();

    outCodecCtx.SetWidth(inCodecCtx.GetWidth());
    outCodecCtx.SetHeight(inCodecCtx.GetHeight());
    //outCodecCtx.SetBitrate(inCodecCtx.GetBitrate());

    outCodecCtx.get()->codec_id = inCodecCtx.get()->codec_id;
    //outCodecCtx.get()->codec_type = inCodecCtx.get()->codec_type;
    outCodecCtx.get()->codec_tag = inCodecCtx.get()->codec_tag;
    //outCodecCtx.get()->has_b_frames = inCodecCtx.get()->has_b_frames;
    //outCodecCtx.get()->bit_rate = inCodecCtx.get()->bit_rate;
    //outCodecCtx.get()->extradata = inCodecCtx.get()->extradata;
    //outCodecCtx.get()->extradata_size = inCodecCtx.get()->extradata_size;

    //if (codec) pOutCodec = avcodec_find_encoder_by_name(codec)->id;

    // Open the output file, write the header

    if (!(outFormatCtx.get()->oformat->flags & AVFMT_NOFILE))
    {
        if (url_fopen(&outFormatCtx.get()->pb, outFormatCtx.get()->filename, URL_WRONLY) < 0)
            fail("Could not open the output file");
    }

    // Parse the video

    if (outFormatCtx.get()->oformat->flags & AVFMT_RAWPICTURE) fail("Raw dump not supported yet");

    long long globaloffset = 0;

    while (optind < argc-1)
    {
        char* file_in = argv[optind];
        fprintf(stderr, "Appending%s\n", file_in);

        InputFormatContext inFormatCtx(file_in);
        Stream inStream = inFormatCtx.GetVideoStream();

        long long localoffset = -1;
        long long pts = 0; // Frame presentation number (Presentation Time Stamp)

        boost::optional<Packet> optInPacket;
        while (optInPacket = inFormatCtx.ReadPacket())
        {
            Packet& inPacket = *optInPacket;

            if (inStream.OwnsPacket(inPacket))
            {
                pts = inPacket.GetPTS();

                if (localoffset < 0) localoffset = pts;

                //fprintf(stderr, "dts=%lu, pts=%lu\n", inPacket.get()->dts, inPacket.get()->pts);

                outStream.OwnPacket(inPacket);
                inPacket.SetPTS(pts-localoffset+globaloffset);
                outFormatCtx.WritePacket(inPacket);
            }
        }

        globaloffset += pts-localoffset + 1;
        optind++;
    }

    return 0;
}
int main(int argc, char *argv[])
{
   // Parse the options

   Timestamp frame_start;
   Timestamp frame_end;
   Timestamp frame_every;
   int width = 0;
   int height = 0;

   int opt;
   while ((opt = getopt(argc, argv, "s:e:t:x:y:")) != -1)
   {
      switch (opt)
      {
         case 's':
            frame_start = Timestamp(optarg);
            break;
         case 'e':
            frame_end = Timestamp(optarg);
            break;
         case 't':
            frame_every = Timestamp(optarg);
            break;
         case 'x':
            width = atoi(optarg);
            break;
         case 'y':
            height = atoi(optarg);
            break;
         default:
            usage(argv[0]);
      }
   }

   if (argc < optind+1) usage(argv[0]);
   if (  frame_end.set &&   frame_end.type != 'd' &&   frame_end.type != 'p' &&   frame_end.type != 's') usage(argv[0]);
   if (frame_start.set && frame_start.type != 'd' && frame_start.type != 'p' && frame_start.type != 's') usage(argv[0]);
   if (frame_every.set && frame_every.type != 'd' && frame_every.type != 'p' && frame_every.type != 's') usage(argv[0]);

   char* file_in = argv[optind];

   // Init all the crap

   av_register_all();

   
   // Open the input file and get the input format context

   InputFormatContext inFormatCtx(file_in);
   
   dump_format(inFormatCtx.get(), 0, file_in, 0); // Just for debugging

   // Find the input video stream

   Stream inStream = inFormatCtx.GetVideoStream();
   
   // Get the input codec context

   CodecContext inCodecCtx = inStream.GetCodecContext();

   if (width == 0 && height == 0) // Same width and height by default
   {
      width = inCodecCtx.GetWidth();
      height = inCodecCtx.GetHeight();
   } else { // Try to keep the aspect ratio
      if (width == 0) width = (int)((float)inCodecCtx.GetWidth() * height/inCodecCtx.GetHeight());
      else if (height == 0) height = (int)((float)inCodecCtx.GetHeight() * width/inCodecCtx.GetWidth());
   }
   
   // Set the resampling context
   
   ScalerContext* pScalerCtx = 0;
   if (inCodecCtx.GetPixelFormat() >= 0)
	pScalerCtx = new ScalerContext(inCodecCtx, width, height, PIX_FMT_GRAY8);

   // Set detector/descriptor stuff

   Image img(width, height);
   lava_ns::ImagePyramid<Image> pyramid;
   pyramid.setScaleFactor(1.2);
   lava_ns::SIFT<Image> descriptor;
   descriptor.setImagePyramid(&pyramid);
   descriptor.setMainParam(61,12,4,8);
   FramePointReceiver receiver(width, height, av_q2d(inStream.GetTimeBase()), descriptor);
   lava_ns::HarrisLaplace<Image> detector;
   detector.setPosThreshold(300);
   detector.setReceiver(&receiver);
   detector.setImage(&pyramid);
   
   // Parse the video

   if (frame_start.set)
   {
	  if (frame_start.type == 's') inFormatCtx.Seek(frame_start.value);
	  if (frame_start.type == 'p') inFormatCtx.Seek(inStream, frame_start.value);	  
   }

   int haveoutput = 0;

   long long dts = 0; // Frame sequence number (Decoding Time Stamp)
   long long pts = 0; // Frame presentation number (Presentation Time Stamp)
   double sec = 0;    // Seconds from the start of the video

   boost::optional<Packet> optInPacket;
   while (optInPacket = inFormatCtx.ReadPacket())
   {
	  Packet& inPacket = *optInPacket;
	   
      if (inStream.OwnsPacket(inPacket))
      {
          pts = inPacket.GetPTS();
          sec = inPacket.GetSeconds(inStream);

          boost::optional<Frame> optInFrame;
          if (optInFrame = inCodecCtx.DecodeFrame(inPacket))
          {
        	Frame& inFrame = *optInFrame;
        	  
        	const char* ftype = inFrame.get()->key_frame ? "I" : "P";
	 
        	bool read = true;
        	if (frame_start.set)
        	{
        		read = false;
        		if (frame_start.type == 'd' && dts >= frame_start.value) read = true;
        		if (frame_start.type == 'p' && pts >= frame_start.value) read = true;
        		if (frame_start.type == 's' && sec >= frame_start.value) read = true;	
        		if (read) frame_start.set = false;
        	}
        	
    		if (read && frame_every.set)
    		{
   				if (frame_start.type != frame_every.type)
   				{
    				if (frame_every.type == 'd') frame_start.value = dts;
    				if (frame_every.type == 'p') frame_start.value = pts;
    				if (frame_every.type == 's') frame_start.value = sec;
   					frame_start.type = frame_every.type; 
   				}
   				frame_start.set = true;
   				frame_start.value += frame_every.value; 
    		}
        	
            if (read)
            {
               if (frame_end.set)
               {
            	   if (frame_end.type == 'd' && dts >= frame_end.value) break;
            	   if (frame_end.type == 'p' && pts >= frame_end.value) break;
            	   if (frame_end.type == 's' && sec >= frame_end.value) break;
               }
	       
               if (!haveoutput)
               {
                  fprintf(stderr, "Starting frame dts=%lld pts=%lld sec=%f (%s)\n", dts, pts, sec, ftype);
                  haveoutput = 1;
               } //else if (dts%DEBUG_FRAMEBLOCK == 0 || inFrame.get()->key_frame) fprintf(stderr, "Copying  frame dts=%lld pts=%lld sec=%f (%s)\n", dts, pts, sec, ftype);

	       if (!pScalerCtx) pScalerCtx = new ScalerContext(inCodecCtx, width, height, PIX_FMT_GRAY8);
               Frame outFrame = pScalerCtx->Rescale(inFrame);
            
               int x,y;
		       for (y=0;y<height;++y)
		       {
		    	   for (x=0;x<width;++x)
		    	   {
		    		   img[y][x] = outFrame.Get8Pixel(x,y);
	               }
		       }

		       receiver.setts(pts);
               pyramid.setImage(&img);
               detector.detect();
            } else {
               //if (dts%DEBUG_FRAMEBLOCK == 0) fprintf(stderr, "Skipping frame dts=%lld pts=%lld sec=%f (%s)\n", dts, pts, sec, ftype);
            }

            dts++;
         }
      }
   }
   fprintf(stderr, "Finished frame dts=%lld pts=%lld sec=%f\n", dts-1, pts, sec);

   if (pScalerCtx) delete pScalerCtx;

   return 0;
}