Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extern "C" {
- #include <libavformat/avformat.h>
- #include <libswscale/swscale.h>
- #include <libavutil/imgutils.h>
- }
- int error;
- AVFormatContext* inputFormatContext = NULL, *outputFormatContext = NULL;
- static AVCodec *decoder_codec;
- static AVCodecContext *decoderContext;
- static AVCodecContext *encoderContext;
- static SwsContext *sws_ctx = nullptr;
- static AVStream* stream;
- static AVFrame *in_hw_frame;
- static AVFrame *out_frame;
- static AVPacket *decode_packet;
- static AVPacket *encode_packet;
- static uint8_t *out_frame_buf;
- //TODO dimension
- int RoundDivision(int dividend, int divisor) {
- return (dividend + (divisor / 2)) / divisor;
- }
- void transcode_frame(char* outputFile) {
- if(!sws_scale(sws_ctx, in_hw_frame->data, in_hw_frame->linesize, 0, in_hw_frame->height, out_frame->data, out_frame->linesize)){
- error = AVERROR_UNKNOWN;
- return;
- }
- av_frame_unref(in_hw_frame);
- error = avcodec_send_frame(encoderContext, out_frame);
- if(error){
- return;
- }
- error = avcodec_receive_packet(encoderContext, encode_packet);
- if(error){
- return;
- }
- FILE* pFile;
- pFile = fopen(outputFile, "wb");
- fwrite(encode_packet->data, 1, encode_packet->size, pFile);
- fclose(pFile);
- av_packet_unref(encode_packet);
- }
- bool read_frame_until_time(int64_t time_in_tb) {
- while (true) {
- if (av_read_frame(inputFormatContext, decode_packet) < 0) {
- return false;
- }
- if (decode_packet->stream_index != stream->index) {
- goto cleanup;
- }
- if (avcodec_send_packet(decoderContext, decode_packet) < 0) {
- goto cleanup;
- }
- if (avcodec_receive_frame(decoderContext, in_hw_frame) < 0) {
- goto cleanup;
- }
- if (in_hw_frame->best_effort_timestamp >= time_in_tb) {
- break;
- }
- cleanup:
- av_frame_unref(in_hw_frame);
- av_packet_unref(decode_packet);
- }
- return true;
- }
- int main(int argc, char **argv){
- if(argc < 3){
- puts("2 arguments are required, input file and output file.");
- return 0;
- }
- char* inputFile = argv[1];
- char* outputFile = argv[2];
- error = avformat_open_input(&inputFormatContext, inputFile, NULL, NULL);
- if (error) {
- return 1;
- }
- error = avformat_find_stream_info(inputFormatContext, NULL);
- if (error) {
- return 1;
- }
- int videoStream = av_find_best_stream(inputFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
- if (videoStream < 0) {
- error = AVERROR_UNKNOWN;
- return 1;
- }
- stream = inputFormatContext->streams[videoStream];
- AVCodecParameters* codecParameters = stream->codecpar;
- if (!codecParameters->codec_id) {
- error = AVERROR_UNKNOWN;
- return 1;
- }
- //Opening input
- decoder_codec = avcodec_find_decoder(codecParameters->codec_id);
- decoderContext = avcodec_alloc_context3(decoder_codec);
- if (!decoderContext) {
- error = AVERROR_UNKNOWN;
- return 1;
- }
- error = avcodec_parameters_to_context(decoderContext, codecParameters);
- if(error){
- return 1;
- }
- decoderContext->thread_count = 0;
- error = avcodec_open2(decoderContext, decoder_codec, nullptr);
- if(error){
- return 1;
- }
- //Opened input
- //init encoder
- avformat_alloc_output_context2(&outputFormatContext, NULL, NULL, outputFile);
- outputFormatContext->video_codec_id = av_guess_codec(outputFormatContext->oformat, NULL, outputFile, NULL, AVMEDIA_TYPE_VIDEO);
- //HERE
- outputFormatContext->video_codec = avcodec_find_encoder(outputFormatContext->video_codec_id);
- if(!outputFormatContext->video_codec){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- encoderContext = avcodec_alloc_context3(outputFormatContext->video_codec);
- if(!encoderContext){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- //dimensions
- encoderContext->width = 270;
- encoderContext->height = 270;
- av_log_set_level(AV_LOG_ERROR);
- encoderContext->pix_fmt = avcodec_find_best_pix_fmt_of_list(outputFormatContext->video_codec->pix_fmts, decoderContext->pix_fmt, true, NULL);
- encoderContext->time_base = av_make_q(1, RoundDivision(stream->avg_frame_rate.num, stream->avg_frame_rate.den) );
- error = avcodec_open2(encoderContext, outputFormatContext->video_codec, nullptr);
- if(error){
- return 1;
- }
- //init encoder
- //TODO dump
- sws_ctx = sws_getContext(decoderContext->width, decoderContext->height, decoderContext->pix_fmt,
- encoderContext->width, encoderContext->height, encoderContext->pix_fmt,
- SWS_LANCZOS, nullptr, nullptr, nullptr);
- if(!sws_ctx){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- //init frames
- in_hw_frame = av_frame_alloc();
- if(!in_hw_frame){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- out_frame = av_frame_alloc();
- if(!out_frame){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- decode_packet = av_packet_alloc();
- if(!decode_packet){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- encode_packet = av_packet_alloc();
- if(!encode_packet){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- out_frame->format = encoderContext->pix_fmt;
- out_frame->width = encoderContext->width;
- out_frame->height = encoderContext->height;
- // instead of directly sending the decoded frame to the encoder, we do a sws scale to convert the frame's pixel format and color range
- // prepare a buffer for the output frame to hold the scaled image data
- const int out_frame_buf_size = av_image_get_buffer_size(encoderContext->pix_fmt, encoderContext->width, encoderContext->height, 1);
- if(out_frame_buf_size < 0){
- error = out_frame_buf_size;
- return 1;
- }
- out_frame_buf = reinterpret_cast<uint8_t *>(av_malloc(out_frame_buf_size));
- if(!out_frame_buf){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- int fillResult = av_image_fill_arrays(out_frame->data, out_frame->linesize, out_frame_buf, encoderContext->pix_fmt, encoderContext->width, encoderContext->height, 1) == out_frame_buf_size;
- if(!fillResult){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- //init frames
- //transcode
- double video_start_time = static_cast<double>(inputFormatContext->start_time) / AV_TIME_BASE;
- const double transcode_start_time = video_start_time;
- int64_t curr_timestamp_in_tb = static_cast<int64_t>(transcode_start_time * stream->time_base.den / stream->time_base.num);
- if (!read_frame_until_time(curr_timestamp_in_tb)) {
- return 1;
- }
- transcode_frame(outputFile);
- av_packet_unref(decode_packet);
- // flush the codec contexts with null packet
- avcodec_send_frame(encoderContext, nullptr);
- avcodec_send_packet(decoderContext, nullptr);
- av_packet_free(&encode_packet);
- av_packet_free(&decode_packet);
- av_frame_free(&out_frame);
- av_frame_free(&in_hw_frame);
- av_free(out_frame_buf);
- sws_freeContext(sws_ctx);
- avcodec_free_context(&encoderContext);
- avcodec_free_context(&decoderContext);
- avformat_close_input(&inputFormatContext);
- //transcode
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement