Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
all:
gcc -Wall -g live_segmenter.c -o live_segmenter -lavformat -lavcodec -lavutil -lbz2 -lm -lz -lfaac -lmp3lame -lx264 -lfaad -lpthread
gcc -Wall -L /usr/lib/ -L /usr/local/lib -g live_segmenter.c -o live_segmenter -lavformat -lavcodec -lavutil -lbz2 -lm -lz -lfaac -lmp3lame -lx264 -lfaad -lpthread

clean:
rm -f live_segmenter
2 changes: 1 addition & 1 deletion hs_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def sanity_check(config)
raise
end

if !File.readable? config['input_location']
if !config['input_location'].match(/^udp:/) and !File.readable? config['input_location']
log.error("The input file can not be read: #{config['input_location']}")
raise
end
Expand Down
74 changes: 74 additions & 0 deletions http_cleaner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env ruby
#
# Copyright (c) 2011 Thomas Christensen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
require 'hs_config'

if ARGV.length != 1
puts "Usage: http_cleaner.rb <config file>"
exit 1
end

begin
config = HSConfig::load( ARGV[0] )
rescue
exit 1
end

log = HSConfig::log_setup( config )

log.info('HTTP Cleaner started')

transfer_config = config[config['transfer_profile']]
streamdir = transfer_config['directory'] + '/'
indexfile = "%s_%s.m3u8" % [config['index_prefix'], config['encoding_profile']]

latestseq = 0
latestfile = ''
nextline = 0

def purge(dir, pattern, timestamp)
puts 'Deleting '+pattern+' files in '+dir+' older than '
puts timestamp
Dir.chdir(dir)
Dir.glob(pattern).each do|f|
curts = File.mtime(f)
if curts < timestamp and !File.directory?(f)
puts 'Purging '+f
File.delete(f)
end
end
end

File.open(streamdir+indexfile).each do |line|
if nextline == 1 and latestfile == ''
latestfile = line.strip
nextline = 0
end
if line[/#EXTINF:5,/]
nextline = 1
end
end
puts 'Looking for time stamp on '+streamdir+latestfile

# Create file name

lastchange = File.mtime(streamdir+latestfile)
purge(streamdir,'*.ts',lastchange)

log.info('HTTP Cleaner stopped')


47 changes: 36 additions & 11 deletions live_segmenter.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static AVStream *add_output_stream(AVFormatContext *output_format_context, AVStr

switch (input_codec_context->codec_type)
{
case CODEC_TYPE_AUDIO:
case AVMEDIA_TYPE_AUDIO:
output_codec_context->channel_layout = input_codec_context->channel_layout;
output_codec_context->sample_rate = input_codec_context->sample_rate;
output_codec_context->channels = input_codec_context->channels;
Expand All @@ -81,7 +81,7 @@ static AVStream *add_output_stream(AVFormatContext *output_format_context, AVStr
output_codec_context->block_align = input_codec_context->block_align;
}
break;
case CODEC_TYPE_VIDEO:
case AVMEDIA_TYPE_VIDEO:
output_codec_context->pix_fmt = input_codec_context->pix_fmt;
output_codec_context->width = input_codec_context->width;
output_codec_context->height = input_codec_context->height;
Expand Down Expand Up @@ -159,7 +159,7 @@ int main(int argc, char **argv)
exit(1);
}

#if LIBAVFORMAT_VERSION_MAJOR >= 52 && LIBAVFORMAT_VERSION_MINOR >= 45
#if LIBAVFORMAT_VERSION_MAJOR > 52 || (LIBAVFORMAT_VERSION_MAJOR == 52 && LIBAVFORMAT_VERSION_MINOR >= 45)
AVOutputFormat *output_format = av_guess_format("mpegts", NULL, NULL);
#else
AVOutputFormat *output_format = guess_format("mpegts", NULL, NULL);
Expand All @@ -178,6 +178,9 @@ int main(int argc, char **argv)
}
output_context->oformat = output_format;

// Don't print warnings when PTS and DTS are identical.
//input_context->flags |= AVFMT_FLAG_IGNDTS;

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

Expand All @@ -189,12 +192,12 @@ int main(int argc, char **argv)
for (i = 0; i < input_context->nb_streams && (video_index < 0 || audio_index < 0); i++)
{
switch (input_context->streams[i]->codec->codec_type) {
case CODEC_TYPE_VIDEO:
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]);
break;
case CODEC_TYPE_AUDIO:
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]);
Expand Down Expand Up @@ -227,6 +230,11 @@ int main(int argc, char **argv)
}
}

if (video_stream->codec->ticks_per_frame > 1)
{
video_stream->codec->time_base.num *= video_stream->codec->ticks_per_frame;
}

unsigned int output_index = 1;
snprintf(output_filename, strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10, "%s/%s-%05u.ts", config.temp_directory, config.filename_prefix, output_index++);
if (url_fopen(&output_context->pb, output_filename, URL_WRONLY) < 0)
Expand All @@ -241,6 +249,10 @@ int main(int argc, char **argv)
exit(1);
}

// Track initial PTS values so we can subtract them out (removing aduio/video delay, since they seem incorrect).
int64_t initial_audio_pts = -1;
int64_t initial_video_pts = -1;

unsigned int first_segment = 1;
unsigned int last_segment = 0;

Expand All @@ -264,13 +276,26 @@ int main(int argc, char **argv)
break;
}

if (packet.stream_index == video_index && (packet.flags & PKT_FLAG_KEY))
if (packet.stream_index == video_index)
{
segment_time = (double)video_stream->pts.val * video_stream->time_base.num / video_stream->time_base.den;
}
else if (video_index < 0)
if (initial_video_pts < 0) initial_video_pts = packet.pts;
packet.pts -= initial_video_pts;
packet.dts = packet.pts;
if (packet.flags & AV_PKT_FLAG_KEY)
{
segment_time = (double)packet.pts * video_stream->time_base.num / video_stream->time_base.den;
}
else
{
segment_time = prev_segment_time;
}
}
else if (packet.stream_index == audio_index)
{
segment_time = (double)audio_stream->pts.val * audio_stream->time_base.num / audio_stream->time_base.den;
if (initial_audio_pts < 0) initial_audio_pts = packet.pts;
packet.pts -= initial_audio_pts;
packet.dts = packet.pts;
segment_time = prev_segment_time;
}
else
{
Expand All @@ -295,7 +320,7 @@ int main(int argc, char **argv)
prev_segment_time = segment_time;
}

ret = av_interleaved_write_frame(output_context, &packet);
ret = av_write_frame(output_context, &packet);
if (ret < 0)
{
fprintf(stderr, "Segmenter error: Could not write frame of stream: %d\n", ret);
Expand Down