Ejemplo n.º 1
0
bool FFmpegBaseWriter::open(const char* filename, int fourcc, double fps, int width, int height,
          bool iscolor, bool need_encode) {
  static const struct AVCodecTag *table[] = { avformat_get_riff_video_tags(), 0 };
  enum AVCodecID id = av_codec_get_id(table, fourcc);

  media_stream_params_t params;
  params.height_video = height;
  params.width_video = width;
  params.video_fps = fps;
  params.codec_id = id;

  stream_ = alloc_video_stream(filename, &params, need_encode);
  channels_ = iscolor ? 3 : 1;

  return true;
}
Ejemplo n.º 2
0
static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, ReportList *reports)
{
	/* Handle to the output file */
	AVFormatContext* of;
	AVOutputFormat* fmt;
	char name[256];
	const char ** exts;

	ffmpeg_type = rd->ffcodecdata.type;
	ffmpeg_codec = rd->ffcodecdata.codec;
	ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
	ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
	ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
	ffmpeg_gop_size = rd->ffcodecdata.gop_size;
	ffmpeg_autosplit = rd->ffcodecdata.flags
		& FFMPEG_AUTOSPLIT_OUTPUT;
	
	do_init_ffmpeg();

	/* Determine the correct filename */
	filepath_ffmpeg(name, rd);
	fprintf(stderr, "Starting output to %s(ffmpeg)...\n"
		"  Using type=%d, codec=%d, audio_codec=%d,\n"
		"  video_bitrate=%d, audio_bitrate=%d,\n"
		"  gop_size=%d, autosplit=%d\n"
		"  render width=%d, render height=%d\n", 
		name, ffmpeg_type, ffmpeg_codec, ffmpeg_audio_codec,
		ffmpeg_video_bitrate, ffmpeg_audio_bitrate,
		ffmpeg_gop_size, ffmpeg_autosplit, rectx, recty);
	
	exts = get_file_extensions(ffmpeg_type);
	if (!exts) {
		BKE_report(reports, RPT_ERROR, "No valid formats found.");
		return 0;
	}
	fmt = av_guess_format(NULL, exts[0], NULL);
	if (!fmt) {
		BKE_report(reports, RPT_ERROR, "No valid formats found.");
		return 0;
	}

	of = avformat_alloc_context();
	if (!of) {
		BKE_report(reports, RPT_ERROR, "Error opening output file");
		return 0;
	}
	
	of->oformat = fmt;
	of->packet_size= rd->ffcodecdata.mux_packet_size;
	if (ffmpeg_audio_codec != CODEC_ID_NONE) {
		of->mux_rate = rd->ffcodecdata.mux_rate;
	} else {
		of->mux_rate = 0;
	}

	of->preload = (int)(0.5*AV_TIME_BASE);
	of->max_delay = (int)(0.7*AV_TIME_BASE);

	fmt->audio_codec = ffmpeg_audio_codec;

	BLI_snprintf(of->filename, sizeof(of->filename), "%s", name);
	/* set the codec to the user's selection */
	switch(ffmpeg_type) {
	case FFMPEG_AVI:
	case FFMPEG_MOV:
	case FFMPEG_MKV:
		fmt->video_codec = ffmpeg_codec;
		break;
	case FFMPEG_OGG:
		fmt->video_codec = CODEC_ID_THEORA;
		break;
	case FFMPEG_DV:
		fmt->video_codec = CODEC_ID_DVVIDEO;
		break;
	case FFMPEG_MPEG1:
		fmt->video_codec = CODEC_ID_MPEG1VIDEO;
		break;
	case FFMPEG_MPEG2:
		fmt->video_codec = CODEC_ID_MPEG2VIDEO;
		break;
	case FFMPEG_H264:
		fmt->video_codec = CODEC_ID_H264;
		break;
	case FFMPEG_XVID:
		fmt->video_codec = CODEC_ID_MPEG4;
		break;
	case FFMPEG_FLV:
		fmt->video_codec = CODEC_ID_FLV1;
		break;
	case FFMPEG_MP3:
		fmt->audio_codec = CODEC_ID_MP3;
	case FFMPEG_WAV:
		fmt->video_codec = CODEC_ID_NONE;
		break;
	case FFMPEG_MPEG4:
	default:
		fmt->video_codec = CODEC_ID_MPEG4;
		break;
	}
	if (fmt->video_codec == CODEC_ID_DVVIDEO) {
		if (rectx != 720) {
			BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!");
			return 0;
		}
		if (rd->frs_sec != 25 && recty != 480) {
			BKE_report(reports, RPT_ERROR, "Render height has to be 480 pixels for DV-NTSC!");
			return 0;
		}
		if (rd->frs_sec == 25 && recty != 576) {
			BKE_report(reports, RPT_ERROR, "Render height has to be 576 pixels for DV-PAL!");
			return 0;
		}
	}
	
	if (ffmpeg_type == FFMPEG_DV) {
		fmt->audio_codec = CODEC_ID_PCM_S16LE;
		if (ffmpeg_audio_codec != CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
			BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
			return 0;
		}
	}
	
	if (fmt->video_codec != CODEC_ID_NONE) {
		video_stream = alloc_video_stream(rd, fmt->video_codec, of, rectx, recty);
		printf("alloc video stream %p\n", video_stream);
		if (!video_stream) {
			BKE_report(reports, RPT_ERROR, "Error initializing video stream.");
			return 0;
		}
	}

	if (ffmpeg_audio_codec != CODEC_ID_NONE) {
		audio_stream = alloc_audio_stream(rd, fmt->audio_codec, of);
		if (!audio_stream) {
			BKE_report(reports, RPT_ERROR, "Error initializing audio stream.");
			return 0;
		}
	}
	if (av_set_parameters(of, NULL) < 0) {
		BKE_report(reports, RPT_ERROR, "Error setting output parameters.");
		return 0;
	}
	if (!(fmt->flags & AVFMT_NOFILE)) {
		if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) {
			BKE_report(reports, RPT_ERROR, "Could not open file for writing.");
			return 0;
		}
	}

	if (av_write_header(of) < 0) {
		BKE_report(reports, RPT_ERROR, "Could not initialize streams. Probably unsupported codec combination.");
		return 0;
	}

	outfile = of;
	av_dump_format(of, 0, name, 1);

	return 1;
}
Ejemplo n.º 3
0
static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports)
{
	/* Handle to the output file */
	AVFormatContext *of;
	AVOutputFormat *fmt;
	AVDictionary *opts = NULL;
	char name[256], error[1024];
	const char **exts;

	context->ffmpeg_type = rd->ffcodecdata.type;
	context->ffmpeg_codec = rd->ffcodecdata.codec;
	context->ffmpeg_audio_codec = rd->ffcodecdata.audio_codec;
	context->ffmpeg_video_bitrate = rd->ffcodecdata.video_bitrate;
	context->ffmpeg_audio_bitrate = rd->ffcodecdata.audio_bitrate;
	context->ffmpeg_gop_size = rd->ffcodecdata.gop_size;
	context->ffmpeg_autosplit = rd->ffcodecdata.flags & FFMPEG_AUTOSPLIT_OUTPUT;

	/* Determine the correct filename */
	ffmpeg_filepath_get(context, name, rd, context->ffmpeg_preview, suffix);
	PRINT("Starting output to %s(ffmpeg)...\n"
	        "  Using type=%d, codec=%d, audio_codec=%d,\n"
	        "  video_bitrate=%d, audio_bitrate=%d,\n"
	        "  gop_size=%d, autosplit=%d\n"
	        "  render width=%d, render height=%d\n",
	        name, context->ffmpeg_type, context->ffmpeg_codec, context->ffmpeg_audio_codec,
	        context->ffmpeg_video_bitrate, context->ffmpeg_audio_bitrate,
	        context->ffmpeg_gop_size, context->ffmpeg_autosplit, rectx, recty);
	
	exts = get_file_extensions(context->ffmpeg_type);
	if (!exts) {
		BKE_report(reports, RPT_ERROR, "No valid formats found");
		return 0;
	}
	fmt = av_guess_format(NULL, exts[0], NULL);
	if (!fmt) {
		BKE_report(reports, RPT_ERROR, "No valid formats found");
		return 0;
	}

	of = avformat_alloc_context();
	if (!of) {
		BKE_report(reports, RPT_ERROR, "Error opening output file");
		return 0;
	}
	
	of->oformat = fmt;
	of->packet_size = rd->ffcodecdata.mux_packet_size;
	if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
		ffmpeg_dict_set_int(&opts, "muxrate", rd->ffcodecdata.mux_rate);
	}
	else {
		av_dict_set(&opts, "muxrate", "0", 0);
	}

	ffmpeg_dict_set_int(&opts, "preload", (int)(0.5 * AV_TIME_BASE));

	of->max_delay = (int)(0.7 * AV_TIME_BASE);

	fmt->audio_codec = context->ffmpeg_audio_codec;

	BLI_strncpy(of->filename, name, sizeof(of->filename));
	/* set the codec to the user's selection */
	switch (context->ffmpeg_type) {
		case FFMPEG_AVI:
		case FFMPEG_MOV:
		case FFMPEG_MKV:
			fmt->video_codec = context->ffmpeg_codec;
			break;
		case FFMPEG_OGG:
			fmt->video_codec = AV_CODEC_ID_THEORA;
			break;
		case FFMPEG_DV:
			fmt->video_codec = AV_CODEC_ID_DVVIDEO;
			break;
		case FFMPEG_MPEG1:
			fmt->video_codec = AV_CODEC_ID_MPEG1VIDEO;
			break;
		case FFMPEG_MPEG2:
			fmt->video_codec = AV_CODEC_ID_MPEG2VIDEO;
			break;
		case FFMPEG_H264:
			fmt->video_codec = AV_CODEC_ID_H264;
			break;
		case FFMPEG_XVID:
			fmt->video_codec = AV_CODEC_ID_MPEG4;
			break;
		case FFMPEG_FLV:
			fmt->video_codec = AV_CODEC_ID_FLV1;
			break;
		case FFMPEG_MPEG4:
		default:
			fmt->video_codec = context->ffmpeg_codec;
			break;
	}
	if (fmt->video_codec == AV_CODEC_ID_DVVIDEO) {
		if (rectx != 720) {
			BKE_report(reports, RPT_ERROR, "Render width has to be 720 pixels for DV!");
			return 0;
		}
		if (rd->frs_sec != 25 && recty != 480) {
			BKE_report(reports, RPT_ERROR, "Render height has to be 480 pixels for DV-NTSC!");
			return 0;
		}
		if (rd->frs_sec == 25 && recty != 576) {
			BKE_report(reports, RPT_ERROR, "Render height has to be 576 pixels for DV-PAL!");
			return 0;
		}
	}
	
	if (context->ffmpeg_type == FFMPEG_DV) {
		fmt->audio_codec = AV_CODEC_ID_PCM_S16LE;
		if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE && rd->ffcodecdata.audio_mixrate != 48000 && rd->ffcodecdata.audio_channels != 2) {
			BKE_report(reports, RPT_ERROR, "FFMPEG only supports 48khz / stereo audio for DV!");
			av_dict_free(&opts);
			return 0;
		}
	}
	
	if (fmt->video_codec != AV_CODEC_ID_NONE) {
		context->video_stream = alloc_video_stream(context, rd, fmt->video_codec, of, rectx, recty, error, sizeof(error));
		PRINT("alloc video stream %p\n", context->video_stream);
		if (!context->video_stream) {
			if (error[0])
				BKE_report(reports, RPT_ERROR, error);
			else
				BKE_report(reports, RPT_ERROR, "Error initializing video stream");

			av_dict_free(&opts);
			return 0;
		}
	}

	if (context->ffmpeg_audio_codec != AV_CODEC_ID_NONE) {
		context->audio_stream = alloc_audio_stream(context, rd, fmt->audio_codec, of, error, sizeof(error));
		if (!context->audio_stream) {
			if (error[0])
				BKE_report(reports, RPT_ERROR, error);
			else
				BKE_report(reports, RPT_ERROR, "Error initializing audio stream");
			av_dict_free(&opts);
			return 0;
		}
	}
	if (!(fmt->flags & AVFMT_NOFILE)) {
		if (avio_open(&of->pb, name, AVIO_FLAG_WRITE) < 0) {
			BKE_report(reports, RPT_ERROR, "Could not open file for writing");
			av_dict_free(&opts);
			return 0;
		}
	}
	if (avformat_write_header(of, NULL) < 0) {
		BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination");
		av_dict_free(&opts);
		avio_close(of->pb);
		return 0;
	}

	context->outfile = of;
	av_dump_format(of, 0, name, 1);
	av_dict_free(&opts);

	return 1;
}
Ejemplo n.º 4
0
int main(int argc, char *argv[]) {
  av_register_all();

  media_stream_params_t params;
  params.height_video = height;
  params.width_video = width;
  params.video_fps = fps;
  params.bit_stream = bit_rate;
  params.codec_id = AV_CODEC_ID_H264;

  media_stream_t* ostream = alloc_video_stream(outfilename, &params, 0);
  if(!ostream){
    return EXIT_FAILURE;
  }

  char errbuf[PCAP_ERRBUF_SIZE];
  pcap_t* pcap = pcap_open_offline_with_tstamp_precision(infilename, PCAP_TSTAMP_PRECISION_NANO, errbuf);
  if (!pcap) {
    fprintf(stderr, "error reading pcap file: %s\n", errbuf);
    free_video_stream(ostream);
    return EXIT_FAILURE;
  }

  struct pcap_pkthdr header;
  const u_char *packet;
  while ((packet = pcap_next(pcap, &header)) != NULL) {
    packet += sizeof(struct vgem_hdr);
    bpf_u_int32 packet_len = header.caplen - sizeof(struct vgem_hdr);
    if (packet_len < sizeof(struct ether_header)) {
      pcap_close(pcap);
      free_video_stream(ostream);
      return EXIT_FAILURE;
    }

    struct ether_header* ethernet_header = (struct ether_header*)packet;
    uint16_t ht = ntohs(ethernet_header->ether_type);
    if (ht != ETHERTYPE_IP) {
      continue;
    }

    /* Skip over the Ethernet header. (14)*/
    packet += sizeof(struct ether_header);
    packet_len -= sizeof(struct ether_header);

    if (packet_len < sizeof(struct ip)) {
      pcap_close(pcap);
      free_video_stream(ostream);
      return EXIT_FAILURE;
    }

    struct iphdr* ip = (struct iphdr*) packet;
    if (!(ip->protocol != IPPROTO_UDP || ip->protocol != IPPROTO_TCP)) {
      continue;
    }

    unsigned int IP_header_length = ip->ihl * 4;  /* ip_hl is in 4-byte words */
    if (packet_len < IP_header_length) { /* didn't capture the full IP header including options */
      pcap_close(pcap);
      free_video_stream(ostream);
      return EXIT_FAILURE;
    }

    packet += IP_header_length;
    packet_len -= IP_header_length;

    if (ip->protocol == IPPROTO_UDP) {
        if (packet_len < sizeof(struct udphdr)) {
          pcap_close(pcap);
          free_video_stream(ostream);
          return EXIT_FAILURE;
        }

        packet += sizeof(struct udphdr);
        packet_len -= sizeof(struct udphdr);

        struct rtp_hdr* rtp = (struct rtp_hdr*)packet;
        if (packet_len < sizeof(struct rtp_hdr)) {
          pcap_close(pcap);
          free_video_stream(ostream);
          return EXIT_FAILURE;
        }

        // rtp payload
        packet += sizeof(struct rtp_hdr);
        packet_len -= sizeof(struct rtp_hdr);
        if (packet_len <= 2) {
          continue;
        }

        uint8_t nal = packet[0];
        uint8_t fragment_type = (nal & 0x1F);

        if (fragment_type >= 1 && fragment_type <= 23) {
          uint8_t* nal_data = NULL;
          size_t size_nal = make_nal_frame_header(packet, packet_len, nal_header, sizeof(nal_header), &nal_data);
          media_stream_write_video_frame(ostream, nal_data, size_nal);
          free(nal_data);
        } else if(fragment_type == 24) {
            packet++;
            packet_len--;
            // first we are going to figure out the total size....
            {
              int total_length= 0;
              uint8_t* dst = NULL;

              int pass;
              for(pass = 0; pass < 2; pass++) {
                  const uint8_t* src = packet;
                  int src_len = packet_len;

                  do {
                      uint16_t nal_size = AV_RB16(src); // this going to be a problem if unaligned (can it be?)

                      // consume the length of the aggregate...
                      src += 2;
                      src_len -= 2;

                      if (nal_size <= src_len) {
                          if(pass==0) {
                              // counting...
                              total_length+= sizeof(nal_header)+nal_size;
                          } else {
                              // copying
                              assert(dst);
                              memcpy(dst, nal_header, sizeof(nal_header));
                              dst += sizeof(nal_header);
                              memcpy(dst, src, nal_size);
                              dst += nal_size;
                          }
                      } else {
                          av_log(NULL, AV_LOG_ERROR,
                                 "nal size exceeds length: %d %d\n", nal_size, src_len);
                      }

                      // eat what we handled...
                      src += nal_size;
                      src_len -= nal_size;

                      if (src_len < 0)
                          av_log(NULL, AV_LOG_ERROR,
                                 "Consumed more bytes than we got! (%d)\n", src_len);
                  } while (src_len > 2);      // because there could be rtp padding..

                  if (pass == 0) {
                    dst = (uint8_t*)calloc(total_length, sizeof(uint8_t));
                  } else {
                  }
              }

          }
        } else if (fragment_type == 28 || fragment_type == 29) {
          packet++;
          packet_len--;

          uint8_t fu_indicator = nal;
          uint8_t fu_header = *packet;   // read the fu_header.
          uint8_t start_bit = fu_header >> 7;
          uint8_t end_bit = (fu_header & 0x40) >> 6;
          uint8_t nal_type = (fu_header & 0x1f);
          uint8_t reconstructed_nal = fu_indicator & (0xe0);  // the original nal forbidden bit and NRI are stored in this packet's nal;
          reconstructed_nal |= nal_type;

          packet++;
          packet_len--;

          if (fragment_type == 29) {
            packet = packet + 2;
            packet_len -= 2;
          }

          CHECK(packet_len > 0);

          if (start_bit) {
            size_t size_nal = sizeof(nal_header) + sizeof(nal) + packet_len;
            uint8_t* nal_data = (uint8_t*)calloc(size_nal, sizeof(uint8_t));
            memcpy(nal_data, nal_header, sizeof(nal_header));
            nal_data[sizeof(nal_header)]= reconstructed_nal;
            memcpy(nal_data + sizeof(nal_header) + sizeof(nal), packet, packet_len);
            media_stream_write_video_frame(ostream, nal_data, size_nal);
            free(nal_data);
          } else {
            media_stream_write_video_frame(ostream, packet, packet_len);
          }
        } else {
          NOTREACHED();
        }

        // http://stackoverflow.com/questions/3493742/problem-to-decode-h264-video-over-rtp-with-ffmpeg-libavcodec
        // http://stackoverflow.com/questions/1957427/detect-mpeg4-h264-i-frame-idr-in-rtp-stream
    } else if (ip->protocol == IPPROTO_TCP) {