Skip to content

Instantly share code, notes, and snippets.

@whatvn
Created October 6, 2014 02:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save whatvn/9ae5678cd5a4090ac469 to your computer and use it in GitHub Desktop.
Save whatvn/9ae5678cd5a4090ac469 to your computer and use it in GitHub Desktop.
ts transcoding
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