Exemple #1
0
int do_calculate_dr(const char *filename) {
	struct stream_context sc;
	struct dr_meter meter;
	int err;

	meter_init(&meter);

	err = sc_open(&sc, filename);
	if (err < 0) { return print_av_error("sc_open", err); }

	int stream_index = err = av_find_best_stream(
		sc.format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
	if (err < 0) { print_av_error("av_find_best_stream", err); goto cleanup; }

	err = sc_start_stream(&sc, stream_index);
	if (err < 0) { print_av_error("sc_start_stream", err); goto cleanup; }

	// Print out the stream info
	AVCodecContext *codec_ctx = sc_get_codec(&sc);
	char codecinfobuf[256];
	avcodec_string(codecinfobuf, sizeof(codecinfobuf), codec_ctx, 0);
	fprintf(stderr, "%.256s\n", codecinfobuf);

	err = meter_start(&meter, codec_ctx->channels, codec_ctx->sample_rate, codec_ctx->sample_fmt);
	if (err) { goto cleanup; }

	fprintf(stderr, "Collecting fragments information...\n");

	size_t fragment = 0;
	int throbbler_stage = 0;
	while (!sc_eof(&sc)) {
		err = sc_get_next_frame(&sc);
		if (err < 0) {
			print_av_error("sc_get_next_frame", err);
			goto cleanup;
		}

		err = meter_feed(&meter, sc.buf, sc.buf_size);
		if (err) { goto cleanup; }

		if (fragment < meter.fragment) {
			fragment = meter.fragment;
			if ((throbbler_stage % 4) == 0) {
				fprintf(stderr, "\033[1K\033[1G %c  %2i:%02i ",
						throbbler[throbbler_stage / 4],
						(fragment * 3) / 60,
						(fragment * 3) % 60);
			}
			throbbler_stage += 1;
			throbbler_stage %= 16;
		}
	}

	meter_finish(&meter);

cleanup:
	meter_free(&meter);
	sc_close(&sc);

	if (err < 0) {
		return err;
	}

	return 0;
}
Exemple #2
0
int calculate_track_dr(const char *filename, struct track_info *t, int number) {
	struct stream_context sc;
	struct dr_meter meter;
	int err;

	meter_init(&meter);

	err = sc_open(&sc, filename);
	if (err < 0) { return print_av_error("sc_open", err); }

	if (debug) {
		printf("DEBUG: Codec: %s\n", avcodec_get_name(sc_get_codec_id(&sc)));
	}


	int stream_index = err = av_find_best_stream(
		sc.format_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
	if (err < 0) { print_av_error("av_find_best_stream", err); goto cleanup; }

	err = sc_start_stream(&sc, stream_index);
	if (err < 0) { print_av_error("sc_start_stream", err); goto cleanup; }

	t->artist = strdup(sc_get_metadata(&sc, "artist"));
	t->album = strdup(sc_get_metadata(&sc, "album"));
        t->tracknumber = strdup(sc_get_metadata(&sc, "track"));
	t->title = strdup(sc_get_metadata(&sc, "title"));

	AVCodecParameters *codecpar = sc_get_codec_parameters(&sc);
	err = meter_start(&meter, codecpar->channels, codecpar->sample_rate, codecpar->format);
	if (err) { goto cleanup; }

	size_t fragment = 0;
	int throbbler_stage = 0;
	while (!sc_eof(&sc)) {
		err = sc_get_next_frame(&sc);
		if (err < 0) {
			print_av_error("sc_get_next_frame", err);
			goto cleanup;
		}

		err = meter_feed(&meter, sc_get_buf(&sc), sc_get_samples(&sc));
		if (err) { goto cleanup; }

		if (fragment < meter.fragment) {
			fragment = meter.fragment;
			if ((throbbler_stage % 4) == 0) {
				fprintf(stderr, "\033[1K\033[1G"
						"Analyzing track %i... "
						"%c  %2zu:%02zu ",
						number,
						throbbler[throbbler_stage / 4],
						(fragment * 3) / 60,
						(fragment * 3) % 60);
			}
			throbbler_stage += 1;
			throbbler_stage %= 16;
		}
	}

	fprintf(stderr, "\033[1K\033[1G");
	meter_finish(&meter, t);

cleanup:
	meter_free(&meter);
	sc_close(&sc);

	if (err < 0) {
		return err;
	}

	return 0;
}
Exemple #3
0
int segment_process(struct config_info config)

{
  unsigned int output_filename_size = sizeof(char) * (strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 100);
  char *output_filename = malloc(output_filename_size);
 
  if (!output_filename) 
  {
    fprintf(stderr, "Segmenter error: Could not allocate space for output filenames\n");
    exit(1);
  }

   
  // we try to approximate the time of first received frame
  // by taking system timestamp and storing first frame timestamp
  time_t sys_time; time(&sys_time);
  double  on_start_timestamp = (double)sys_time;

  av_register_all();

  AVInputFormat *input_format = av_find_input_format("mpegts");
  if (!input_format) 
  {
    fprintf(stderr, "Segmenter error: Could not find MPEG-TS demuxer\n");
    exit(1);
  }

  AVFormatContext *input_context = NULL;
  int ret;
  ret  = avformat_open_input(&input_context, config.input_filename, input_format,  NULL);
  if (ret != 0) 
  {
	print_av_error("Could not open input file, make sure it is an mpegts", ret);
    exit(1);
  }

  ret = avformat_find_stream_info(input_context, NULL);
  if (ret < 0) 
  {
	print_av_error("Could not read stream information", ret);
    exit(1);
  }

  fprintf(stderr, "segmenter-debug: start time %lld %lld \n", input_context->start_time, input_context->timestamp);

  AVOutputFormat *output_format = av_guess_format("mpegts", NULL, NULL);
  if (!output_format) 
  {
    fprintf(stderr, "Segmenter error: Could not find MPEG-TS muxer\n");
    exit(1);
  }

  AVFormatContext *output_context = avformat_alloc_context();
  if (!output_context) 
  {
    fprintf(stderr, "Segmenter error: Could not allocated output context");
    exit(1);
  }
  output_context->oformat = output_format;

  int video_index = -1;
  int audio_index = -1;

  AVStream *video_stream;
  AVStream *audio_stream;

  int i;
  int index_map[20];
  memset (index_map, -1, sizeof(int)*20);

  for (i = 0; i < input_context->nb_streams && (video_index < 0 || audio_index < 0); i++) 
  {
    switch (input_context->streams[i]->codec->codec_type) {
      case AVMEDIA_TYPE_VIDEO:
        video_index = i;
        input_context->streams[i]->discard = AVDISCARD_NONE;
        video_stream = add_output_stream(output_context, input_context->streams[i]);
	index_map[i] = video_stream->index;
        break;
      case AVMEDIA_TYPE_AUDIO:
        audio_index = i;
        input_context->streams[i]->discard = AVDISCARD_NONE;
        audio_stream = add_output_stream(output_context, input_context->streams[i]);
	index_map[i] = audio_stream->index;
        break;
      default:
        input_context->streams[i]->discard = AVDISCARD_ALL;
        fprintf(stderr, "segmenter-warning: stream index %d from source woudl be skipped \n", i);
        break;
    }
  }
#if LIBAVFORMAT_VERSION_MAJOR < 54
  if (av_set_parameters(output_context, NULL) < 0) 
  {
    fprintf(stderr, "Segmenter error: Invalid output format parameters\n");
    exit(1);
  }
#endif

  av_dump_format(output_context, 0, config.filename_prefix, 1);

  if(video_index >= 0)
  {
    AVCodec *codec = avcodec_find_decoder(video_stream->codec->codec_id);
    if (!codec) 
    {
      fprintf(stderr, "Segmenter error: Could not find video decoder, key frames will not be honored\n");
    }

    if (avcodec_open2(video_stream->codec, codec, NULL) < 0) 
    {
      fprintf(stderr, "Segmenter error: Could not open video decoder, key frames will not be honored\n");
    }
  }

  unsigned int output_index = 1;
  snprintf(output_filename, output_filename_size, "%s/%s-%u-%010u.ts", config.temp_directory, config.filename_prefix, config.run_cycle, output_index++);
  if (avio_open(&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0) 
  {
    fprintf(stderr, "Segmenter error: Could not open '%s'\n", output_filename);
    exit(1);
  }

  if (avformat_write_header(output_context, NULL)) 
  {
    fprintf(stderr, "Segmenter error: Could not write mpegts header to first output file\n");
    exit(1);
  }

  unsigned int first_segment = 1;
  unsigned int last_segment = 0;
  
  double prev_segment_time = 0;
  double first_segment_time = -1.0;
  int decode_done;
  double segment_time = 0;
  
  unsigned int pktWriteFrameErrorCount = 0;
  do 
  {
    AVPacket packet;

    decode_done = av_read_frame(input_context, &packet);
    if (decode_done < 0) 
    {
      break;
    }

    if ((ret = av_dup_packet(&packet)) < 0) 
    {
      print_av_error("Could not duplicate packet", ret);
      av_free_packet(&packet);
      break;
    }

    if (packet.stream_index == video_index && (packet.flags & AV_PKT_FLAG_KEY)) 
    {
      segment_time = (double)video_stream->pts.val * video_stream->time_base.num / video_stream->time_base.den;
      if (first_segment_time <= 0) 
         fprintf(stderr, "segmenter-debug: received new time from video I frame : %lf\n", segment_time);
    }
    else if (video_index < 0) 
    {
      segment_time = (double)audio_stream->pts.val * audio_stream->time_base.num / audio_stream->time_base.den;
      if (first_segment_time <= 0)
         fprintf(stderr, "segmenter-debug: received new time from audio PTS : %lf\n", segment_time);
    }
    else 
    {
      segment_time = prev_segment_time;
    }

    // initialy previous segment time would be zero, avoid receiving huge difference
    if (prev_segment_time == 0 && segment_time > 0) {
        prev_segment_time = segment_time;
    }

    if (first_segment_time < 0 && segment_time > 0) {
	first_segment_time = segment_time; // this is relative time in MS
    }
    
    //fprintf(stderr, "segmenter-debug: videoPTS=%lf audioPTS=%lf\n", (double)video_stream->pts.val * video_stream->time_base.num / video_stream->time_base.den, (double)audio_stream->pts.val * audio_stream->time_base.num / audio_stream->time_base.den); 
    //fprintf(stderr, "segmenter-debug: cur=%.02lf prev=%.02lf onstartTS=%.02lf first=%.02lf\n", segment_time, prev_segment_time, on_start_timestamp, first_segment_time);

    // timestamps in the streams received from IRDs are relative, 
    // if there's a mismatch - time to restart segmentation process, as entire TS may change
    
    // done writing the current file?
    if (segment_time - prev_segment_time >= config.segment_length) 
    {
      avio_flush(output_context->pb);
      avio_close(output_context->pb);

      output_transfer_command(++last_segment, (segment_time-first_segment_time+on_start_timestamp), (segment_time-prev_segment_time), 0, output_filename);

      snprintf(output_filename, output_filename_size, "%s/%s-%u-%010u.ts", config.temp_directory, config.filename_prefix, config.run_cycle,output_index++);
      if (avio_open(&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0) 
      {
        fprintf(stderr, "Segmenter error: Could not open '%s'\n", output_filename);
        break;
      }

      prev_segment_time = segment_time;
    }
    
    
    // because indicies from original and destination packets differ, perform correction
    if (index_map[packet.stream_index] < 0) {
	  fprintf(stderr, "segmenter-debug: skipping packet pos=%lld size=%d stream=%d flags=%d pts=%lld\n", packet.pos, packet.size, packet.stream_index, packet.flags, packet.pts); 
      ret = -1000;
    }else if (packet.size > 0) {
  	    packet.stream_index = index_map[packet.stream_index];
    	ret = av_interleaved_write_frame(output_context, &packet);
        // fprintf(stderr, "segmenter-error: [%d] handling packet pos=%lld size=%d stream=%d flags=%d pts=%lld\n", ret, packet.pos, packet.size, packet.stream_index, packet.flags, packet.pts);
	}else{
		fprintf(stderr, "segmenter-debug: empty packet\n");
		ret = -1001;
    }
    av_free_packet(&packet);
    
    if (ret < 0) 
    {
      // fprintf(stderr, "segmenter-error: handling packet pos=%lld size=%d stream=%d flags=%d pts=%lld\n", packet.pos, packet.size, packet.stream_index, packet.flags, packet.pts);
      // print_av_error("av_interleaved_write_frame ",ret);
      pktWriteFrameErrorCount ++;
      if (first_segment_time > 0 && pktWriteFrameErrorCount > PKT_WRITE_FRAME_ERROR_LIMIT) {
          fprintf(stderr, "segmenter-error: can't handle last %u packets. requesting process restart.\n", pktWriteFrameErrorCount);
          break;
      }
    }
    else if (ret > 0) 
    {
      fprintf(stderr, "Segmenter info: End of stream requested\n");
      av_free_packet(&packet);
      break;
    }else{
      pktWriteFrameErrorCount = 0; // clear av_interleaved_write_frame() error count
    }
  } while (!decode_done);

  av_write_trailer(output_context);

  if (video_index >= 0) 
  {
    avcodec_close(video_stream->codec);
  }

  for(i = 0; i < output_context->nb_streams; i++) 
  {
    av_freep(&output_context->streams[i]->codec);
    av_freep(&output_context->streams[i]);
  }

  avio_close(output_context->pb);
  av_free(output_context);
  av_close_input_file(input_context);

      output_transfer_command(++last_segment, (segment_time-first_segment_time+on_start_timestamp), (segment_time-prev_segment_time), 1, output_filename);
  return 0;
}