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;
- AVFormatContext* outputFormatContext = NULL;
- AVCodecContext* encoderContext;
- AVCodecContext* decoderContext;
- SwsContext *swsCtx = nullptr;
- AVPacket* decodePacket;
- AVCodec* decoderCodec;
- uint8_t *dst_data[4];
- int dst_linesize[4];
- uint8_t* outputFrameBuffer;
- AVPacket* encodePacket;
- AVFrame* inputFrame;
- AVFrame* outputFrame;
- FILE *dst_file;
- int dst_bufsize;
- int ret;
- //TODO dimension
- 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 streamIndex = av_find_best_stream(inputFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
- if (streamIndex < 0) {
- error = AVERROR_UNKNOWN;
- return 1;
- }
- AVStream* stream = inputFormatContext->streams[streamIndex];
- AVCodecParameters* codecParameters = stream->codecpar;
- if (!codecParameters->codec_id) {
- error = AVERROR_UNKNOWN;
- return 1;
- }
- //Opening input
- decoderCodec = avcodec_find_decoder(codecParameters->codec_id);
- decoderContext = avcodec_alloc_context3(decoderCodec);
- 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, decoderCodec, nullptr);
- if(error){
- return 1;
- }
- //Opened input
- //init frames
- inputFrame = av_frame_alloc();
- if(!inputFrame){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- outputFrame = av_frame_alloc();
- if(!outputFrame){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- decodePacket = av_packet_alloc();
- if(!decodePacket){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- encodePacket = av_packet_alloc();
- if(!encodePacket){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- //TODO
- //open file
- dst_file = fopen(outputFile, "wb");
- if (!dst_file) {
- fprintf(stderr, "Could not open destination file %s\n", outputFile);
- return 1;
- }
- avformat_alloc_output_context2(&outputFormatContext, NULL, NULL, outputFile);
- outputFormatContext->video_codec_id = av_guess_codec(outputFormatContext->oformat, NULL, outputFile, NULL, AVMEDIA_TYPE_VIDEO);
- 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;
- }
- encoderContext->width = 100;
- encoderContext->height = 100;
- 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, (stream->avg_frame_rate.num + (stream->avg_frame_rate.den / 2)) / stream->avg_frame_rate.den);
- error = avcodec_open2(encoderContext, outputFormatContext->video_codec, nullptr);
- if(error){
- return 1;
- }
- //init encoder
- swsCtx = sws_getContext(decoderContext->width, decoderContext->height, decoderContext->pix_fmt,
- encoderContext->width, encoderContext->height, encoderContext->pix_fmt,
- 0, nullptr, nullptr, nullptr);
- if(!swsCtx){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- outputFrame->format = encoderContext->pix_fmt;
- outputFrame->width = encoderContext->width;
- outputFrame->height = encoderContext->height;
- int align = 4;
- int outputFrameBufferSize = av_image_get_buffer_size(encoderContext->pix_fmt, encoderContext->width, encoderContext->height, align);
- if(outputFrameBufferSize < 0){
- error = outputFrameBufferSize;
- return 1;
- }
- outputFrameBuffer = reinterpret_cast<uint8_t *>(av_malloc(outputFrameBufferSize));
- if(!outputFrameBuffer){
- error = AVERROR_UNKNOWN;
- return 1;
- }
- int fillResult = av_image_fill_arrays(outputFrame->data, outputFrame->linesize, outputFrameBuffer, encoderContext->pix_fmt, encoderContext->width, encoderContext->height, align) == outputFrameBufferSize;
- /* if(!fillResult) {
- puts("size mismatch");
- error = AVERROR_UNKNOWN;
- return 1;
- }*/
- while (true) {
- av_frame_unref(inputFrame);
- av_packet_unref(decodePacket);
- error = av_read_frame(inputFormatContext, decodePacket);
- //probably ended frames
- if(error < 0){
- break;
- }
- //different stream. ignore.
- if (decodePacket->stream_index != streamIndex) {
- continue;
- }
- //send packet
- error = avcodec_send_packet(decoderContext, decodePacket);
- if (error < 0 ) {
- //get next one
- if (error == AVERROR(EAGAIN)){
- continue;
- } else {
- return 1;
- }
- }
- //send frame
- error = avcodec_receive_frame(decoderContext, inputFrame);
- if (error < 0) {
- //get next one
- if (error == AVERROR(EAGAIN)){
- continue;
- } else {
- return 1;
- }
- }
- //we need to get the data
- if(!sws_scale(swsCtx, inputFrame->data,
- inputFrame->linesize, 0, inputFrame->height, outputFrame->data, outputFrame->linesize)){
- return 1;
- }
- error = avcodec_send_frame(encoderContext, outputFrame);
- if(error){
- return 1;
- }
- error = avcodec_receive_packet(encoderContext, encodePacket);
- if(error){
- return 1;
- }
- fwrite(encodePacket->data, 1, encodePacket->size, dst_file);
- }
- //TODO
- // 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
- fclose(dst_file);
- av_packet_unref(decodePacket);
- // flush the codec contexts with null packet
- avcodec_send_packet(decoderContext, nullptr);
- av_packet_free(&decodePacket);
- av_frame_free(&inputFrame);
- sws_freeContext(swsCtx);
- av_packet_free(&decodePacket);
- av_frame_free(&outputFrame);
- avcodec_free_context(&encoderContext);
- avcodec_free_context(&decoderContext);
- avformat_close_input(&inputFormatContext);
- avformat_free_context(outputFormatContext);
- av_free(outputFrameBuffer);
- //transcode
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement