Created
October 6, 2014 02:17
-
-
Save whatvn/9ae5678cd5a4090ac469 to your computer and use it in GitHub Desktop.
ts transcoding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int in_video_index = -1; | |
int in_audio_index = -1; | |
int return_code = ERROR; | |
int buffer_size; | |
unsigned char *exchange_area; | |
AVFormatContext *input_format_context = NULL; | |
AVFormatContext *output_format_context = NULL; | |
AVIOContext *io_context; | |
AVCodec *input_audio_codec = NULL; | |
AVCodec *output_audio_codec = NULL; | |
AVCodec *input_video_codec = NULL; | |
AVCodec *output_video_codec = NULL; | |
AVCodecContext *input_audio_codec_context = NULL; | |
AVCodecContext *input_video_codec_context = NULL; | |
AVCodecContext *output_audio_codec_context = NULL; | |
AVCodecContext *output_video_codec_context = NULL; | |
AVStream *input_video_stream = NULL; | |
AVStream *input_audio_stream = NULL; | |
AVStream *output_video_stream = NULL; | |
AVStream *output_audio_stream = NULL; | |
int output_audio_index = -1; | |
int output_video_index = -1; | |
int ret = -1; | |
av_log_set_level(AV_LOG_DEBUG); | |
av_register_all(); | |
output_format_context = avformat_alloc_context(); | |
if (!output_format_context) { | |
log_error(LOG_ERR, log, 0, "streaming module: could not alloc output context"); | |
goto exit; | |
} | |
buffer_size = 10240; | |
exchange_area = malloc(pool, buffer_size * sizeof (unsigned char)); | |
io_context = avio_alloc_context(exchange_area, buffer_size, 1, (void *) destination, NULL, write_adbr_packet, NULL); | |
output_format_context->pb = io_context; | |
output_format_context->oformat = av_guess_format("mpegts", NULL, NULL); | |
if (avformat_open_input(&input_format_context, (char *) source, NULL, NULL) < 0) { | |
log_error(LOG_ERR, log, 0, "streaming module: could not open video input: '%s'", source); | |
return_code = SEGMENT_NOT_FOUND; | |
goto exit; | |
} | |
if (avformat_find_stream_info(input_format_context, NULL) < 0) { | |
log_error(LOG_ERR, log, 0, "streaming module: could not find stream info"); | |
goto exit; | |
} | |
// allcate context for audio | |
in_audio_index = av_find_best_stream(input_format_context, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, -1); | |
if (in_audio_index >= 0) { | |
input_format_context->streams[in_audio_index]->discard = AVDISCARD_NONE; | |
input_audio_stream = input_format_context->streams[in_audio_index]; | |
input_audio_codec_context = input_audio_stream->codec; | |
input_audio_codec = avcodec_find_decoder(input_audio_codec_context->codec_id); | |
output_audio_stream = add_output_stream(output_format_context, input_audio_stream); | |
output_audio_index = output_audio_stream->index; | |
if (!output_audio_stream) { | |
fprintf(stderr, "Cannot add audio stream\n"); | |
goto exit; | |
} | |
if (!(input_audio_codec)) { | |
fprintf(stderr, "Cannot find decoder for input audio codec\n"); | |
goto exit; | |
} | |
ret = avcodec_open2(input_audio_codec_context, input_audio_codec, 0); | |
if (ret < 0) { | |
fprintf(stderr, "Cannot open input audio codec\n"); | |
goto exit; | |
} | |
} | |
// allcate context for video | |
in_video_index = av_find_best_stream(input_format_context, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, -1); | |
if (in_video_index >= 0) { | |
input_format_context->streams[in_video_index]->discard = AVDISCARD_NONE; | |
input_video_stream = input_format_context->streams[in_video_index]; | |
input_video_codec_context = input_video_stream->codec; | |
input_video_codec = avcodec_find_decoder(input_video_codec_context->codec_id); | |
// input_video_codec = avcodec_find_decoder_by_name("libx264"); | |
output_video_stream = add_output_stream(output_format_context, input_video_stream); | |
output_video_index = output_video_stream->index; | |
if (!output_video_stream) { | |
fprintf(stderr, "Cannot add video stream\n"); | |
goto exit; | |
} | |
if (!(input_video_codec)) { | |
fprintf(stderr, "Cannot find decoder for input video codec\n"); | |
goto exit; | |
} | |
ret = avcodec_open2(input_video_codec_context, input_video_codec, 0); | |
if (ret < 0) { | |
fprintf(stderr, "Cannot open input video codec\n"); | |
goto exit; | |
} | |
} | |
av_dump_format(input_format_context, 0, (const char *) source, 0); | |
//prepare output codec context | |
// Setup video stream | |
if (in_video_index >= 0) { | |
output_video_codec = avcodec_find_encoder_by_name("libx264"); | |
if (!output_video_codec) { | |
fprintf(stderr, "Can't open output video codec\n"); | |
goto exit; | |
} | |
output_video_codec_context = avcodec_alloc_context3(output_video_codec); | |
if (!output_video_codec_context) { | |
fprintf(stderr, "Can't allocate video codec context\n"); | |
goto exit; | |
} | |
output_video_codec_context->width = input_video_codec_context->width; | |
output_video_codec_context->height = input_video_codec_context->height; | |
// output_video_codec_context->width = 640; | |
// output_video_codec_context->height = 480; | |
output_video_codec_context->time_base.den = 25; | |
output_video_codec_context->time_base.num = 1; | |
output_video_codec_context->bit_rate = 500000; | |
output_video_codec_context->bit_rate_tolerance = 0; | |
output_video_codec_context->rc_max_rate = 0; | |
output_video_codec_context->rc_buffer_size = 0; | |
output_video_codec_context->gop_size = 40; | |
output_video_codec_context->max_b_frames = 3; | |
output_video_codec_context->b_frame_strategy = 1; | |
output_video_codec_context->coder_type = 1; | |
output_video_codec_context->me_cmp = 1; | |
output_video_codec_context->me_range = 16; | |
output_video_codec_context->qmin = 10; | |
output_video_codec_context->qmax = 51; | |
output_video_codec_context->sample_rate = 90; | |
output_video_codec_context->scenechange_threshold = 40; | |
output_video_codec_context->flags |= CODEC_FLAG_LOOP_FILTER; | |
output_video_codec_context->me_method = ME_HEX; | |
output_video_codec_context->me_subpel_quality = 5; | |
output_video_codec_context->i_quant_factor = 0.71; | |
output_video_codec_context->qcompress = 0.6; | |
output_video_codec_context->max_qdiff = 4; | |
output_video_codec_context->flags2 |= CODEC_FLAG2_SHOW_ALL; | |
output_video_codec_context->gop_size = 12; | |
output_video_codec_context->pix_fmt = input_video_codec_context->pix_fmt; | |
av_opt_set(output_video_codec_context->priv_data, "preset", "veryfast", 0); | |
// Open codec | |
if (avcodec_open2(output_video_codec_context, output_video_codec, 0) < 0) { | |
fprintf(stderr, "Can't open output video codec context\n"); | |
goto exit; | |
} | |
} | |
// Setup audio stream | |
if (in_audio_index >= 0) { | |
output_audio_codec = avcodec_find_encoder_by_name("libfdk_aac"); | |
if (!output_audio_codec) { | |
fprintf(stderr, "Can't open output audio codec\n"); | |
goto exit; | |
} | |
output_audio_codec_context = avcodec_alloc_context3(output_audio_codec); | |
if (!output_audio_codec_context) { | |
fprintf(stderr, "Can't allocate audio codec context\n"); | |
goto exit; | |
} | |
output_audio_codec_context->sample_fmt = AV_SAMPLE_FMT_S16; | |
output_audio_codec_context->bit_rate = input_audio_codec_context->bit_rate; | |
output_audio_codec_context->sample_rate = input_audio_codec_context->sample_rate; | |
output_audio_codec_context->channels = input_audio_codec_context->channels; | |
output_audio_codec_context->channel_layout = input_audio_codec_context->channel_layout; | |
if (avcodec_open2(output_audio_codec_context, output_audio_codec, 0) < 0) { | |
fprintf(stderr, "Can't open output audio codec context\n"); | |
goto exit; | |
} | |
} | |
if (avformat_write_header(output_format_context, NULL) < 0) { | |
goto exit; | |
fprintf(stderr, "cant write video header\n "); | |
} | |
AVFrame *frame = NULL; | |
AVPacket packet; | |
av_init_packet(&packet); | |
packet.data = NULL; | |
packet.size = 0; | |
int got_frame; | |
uint64_t input_audio_samples = 0; | |
int frame_count = 0; | |
while (av_read_frame(input_format_context, &packet) >= 0) { | |
AVPacket output_packet; | |
output_packet.data = NULL; | |
output_packet.size = 0; | |
av_init_packet(&output_packet); | |
int got_packet = 0; | |
frame = av_frame_alloc(); | |
if (!frame) { | |
return return_code; | |
} | |
if (packet.stream_index == in_video_index) { | |
fprintf(stderr, "Processing video frame index %d\n", in_video_index); | |
ret = avcodec_decode_video2(input_video_codec_context, frame, &got_frame, &packet); | |
if (ret < 0) { | |
fprintf(stderr, "cannot decode video frame, error: %d\n", ret); | |
goto exit; | |
} | |
if (got_frame) { | |
// encode | |
fprintf(stderr, "we got video frame: %d\n", frame_count); | |
frame->pict_type = 0; | |
frame->pts = (1.0 / 30) * output_video_codec_context->sample_rate * frame_count; | |
//frame->pts = frame_count; | |
frame_count++; | |
ret = avcodec_encode_video2(output_video_codec_context, &output_packet, frame, &got_packet); | |
if (frame != NULL) { | |
av_frame_free(&frame); | |
frame = NULL; | |
} | |
if (ret >= 0) { | |
fprintf(stderr, "Encoding video frame successfully %d\n", frame_count); | |
output_packet.stream_index = output_video_index; | |
// rescale no matter what | |
if (output_packet.pts != (signed) AV_NOPTS_VALUE) | |
output_packet.pts = av_rescale_q(output_packet.pts, output_video_codec_context->time_base, output_video_stream->time_base); | |
if (output_packet.dts != (signed) AV_NOPTS_VALUE) | |
output_packet.dts = av_rescale_q(output_packet.dts, output_video_codec_context->time_base, output_video_stream->time_base); | |
if (output_video_codec_context->coded_frame->key_frame) { | |
output_packet.flags |= AV_PKT_FLAG_KEY; | |
} | |
} else { | |
fprintf(stderr, "cannot encode video frame error: %d\n", ret); | |
return return_code; | |
} | |
} | |
} else if (packet.stream_index == in_audio_index) { | |
ret = avcodec_decode_audio4(input_audio_codec_context, frame, &got_frame, &packet); | |
if (ret < 0) { | |
fprintf(stderr, "Cannot decode audio stream, error: %d\n", ret); | |
return return_code; | |
} | |
if (got_frame) { | |
fprintf(stderr, "we got audio frame:" "%" PRIu64 "\n", input_audio_samples); | |
frame->pict_type = 0; | |
frame->pts = input_audio_samples; | |
input_audio_samples += frame->nb_samples; | |
fprintf(stderr, "we came here and die 5644\n"); | |
ret = avcodec_encode_audio2(output_audio_codec_context, &output_packet, frame, &got_packet); | |
if (frame != NULL) { | |
av_frame_free(&frame); | |
frame = NULL; | |
} | |
fprintf(stderr, "we came here and die 5646\n"); | |
if (ret >= 0) { | |
output_packet.stream_index = output_audio_index; | |
if (output_packet.pts != (signed) AV_NOPTS_VALUE) { | |
output_packet.pts = av_rescale_q(output_packet.pts, output_audio_codec_context->time_base, output_audio_stream->time_base); | |
} | |
if (output_packet.dts != (signed) AV_NOPTS_VALUE) { | |
output_packet.dts = av_rescale_q(output_packet.dts, output_audio_codec_context->time_base, output_audio_stream->time_base); | |
} | |
} else { | |
fprintf(stderr, "Cannot encode audio frame, error: %d\n", ret); | |
return return_code; | |
} | |
} | |
} | |
if (got_packet && output_packet.data && (output_packet.size > 0)) { | |
fprintf(stderr, "Packet pts :" "%" PRId64 "\n", output_packet.pts); | |
fprintf(stderr, "Packet dts :" "%" PRId64 "\n", output_packet.dts); | |
ret = av_interleaved_write_frame(output_format_context, &output_packet); | |
if (ret < 0) { | |
av_free_packet(&packet); | |
fprintf(stderr, "Cannot finalize writing packet, error: %d\n", ret); | |
return return_code; | |
} else { | |
fprintf(stderr, "Successfully write packet: %d\n", ret); | |
} | |
} | |
if (frame != NULL) { | |
av_frame_free(&frame); | |
frame = NULL; | |
} | |
av_free_packet(&packet); | |
} | |
av_write_trailer(output_format_context); | |
unsigned int i; | |
for (i = 0; i < output_format_context->nb_streams; i++) { | |
av_freep(&output_format_context->streams[i]->codec); | |
av_freep(&output_format_context->streams[i]); | |
} | |
if (!(output_format_context->oformat->flags & AVFMT_NOFILE)) { | |
av_freep(output_format_context->pb); | |
} | |
if (output_format_context != NULL) { | |
av_free(output_format_context); | |
output_format_context = NULL; | |
} | |
if (input_format_context != NULL) { | |
avformat_close_input(&input_format_context); | |
input_format_context = NULL; | |
} | |
av_free(io_context); | |
return_code = OK; | |
exit: | |
fprintf(stderr, "Fall back to not using adbr\n"); | |
if (output_format_context != NULL) { | |
av_free(output_format_context); | |
output_format_context = NULL; | |
} | |
if (input_format_context != NULL) { | |
avformat_close_input(&input_format_context); | |
input_format_context = NULL; | |
} | |
return return_code; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment