[Libav-user] Copying audio stream

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[Libav-user] Copying audio stream

David Barishev

Hello all!
I am trying to replicate this ffmpeg command: ffmpeg -i <input> -vn -acodec copy <output>, using the libav APIs.

There seems to be a lack of updated examples and i really struggled to find any resources.
I was able to open the file both input and output, allocate format contexts for each, and copy general stream information, but not the packets themselves.

Here is the code that i gathered with some comments i have added,btw im running it on android :

void ffmpeg(
            const char *in_filename,
            const char *out_filename 
    ) {

        //Libraries init
        SSL_load_error_strings();
        SSL_library_init();

        av_register_all ();
        avformat_network_init ();

        //Set avlog to log on locat
        av_log_set_callback(log_callback_android);

        AVOutputFormat *ofmt = NULL;
        AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
        AVPacket pkt;
        int ret, i;

        // Opening input file, and checking stream info
        if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
            __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Could not open input file '%s'.Error %s", in_filename, av_err2str(ret));
            goto end;
        }
        if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
            __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Failed to retrieve input stream information");
            goto end;
        }

        //Print stream info
        av_dump_format(ifmt_ctx, 0, in_filename, 0);


        //Allocate new contex for output file
        avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
        if (!ofmt_ctx) {
            __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Could not create output context\n");
            ret = AVERROR_UNKNOWN;
            goto end;
        }

        //Setting output format to inhereted format
        ofmt = ofmt_ctx->oformat;

        // Iterate over all streams in input file
        for (i = 0; i < ifmt_ctx->nb_streams; i++) {
            //Stream input
            AVStream *in_stream = ifmt_ctx->streams[i];

            //Filter non audio streams
            if(in_stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO){
                __android_log_print(ANDROID_LOG_INFO,APPNAME,"Audio stream found");

                //in_stream->codec is deprecated, no idea how to get it otherway
                //Making new stream in the output format context, based on the input stream
                AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
                if (!out_stream) {
                    __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Failed allocating output stream\n");
                    ret = AVERROR_UNKNOWN;
                    goto end;
                }

                //Copying stream information to new contex 
                ret = avcodec_parameters_copy(out_stream->codecpar,in_stream->codecpar);
                if (ret < 0) {
                    __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Failed to copy context from input to output stream codec context\n");
                    goto end;
                }

            }

        }
        //Print output format
        av_dump_format(ofmt_ctx, 0, out_filename, 1);

        //Open output file
        if (!(ofmt->flags & AVFMT_NOFILE)) {
            ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
            if (ret < 0) {
                __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Could not open output file '%s'", out_filename);
                goto end;
            }
        }

        //Writing output header
        ret = avformat_write_header(ofmt_ctx, NULL);
        if (ret < 0) {
            __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Error occurred when opening output file\n");
            goto end;
        }

        //Mux packets - dont know what is happening here, assuming its copying the real data to the streams.
        while (1) {
            AVStream *in_stream, *out_stream;
            ret = av_read_frame(ifmt_ctx, &pkt);
            if (ret < 0)
                break;

            in_stream  = ifmt_ctx->streams[pkt.stream_index];
            out_stream = ofmt_ctx->streams[pkt.stream_index];
            log_packet(ifmt_ctx, &pkt, "in");
            //copy packet
            pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_PASS_MINMAX);
            pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_PASS_MINMAX);
            pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
            pkt.pos = -1;
            log_packet(ofmt_ctx, &pkt, "out");
            ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
            if (ret < 0) {
                __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Error muxing packet\n");
                break;
            }
            av_packet_unref(&pkt);
        }
        av_write_trailer(ofmt_ctx);

        end:
        avformat_close_input(&ifmt_ctx);
        //close output
        if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
            avio_closep(&ofmt_ctx->pb);
        //free output alloc
        avformat_free_context(ofmt_ctx);
        if (ret < 0 && ret != AVERROR_EOF) {
            __android_log_print(ANDROID_LOG_ERROR, APPNAME, "Error occurred: %s\n", av_err2str(ret));

        }
    }

The muxing packets part,doesnt work, as it failed with signal error, after few iterations - probably error in this code, nothing to do with the libs themselves.

Here is an ouput of a run:

===Input Information===

    Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '<input>':
      Metadata:
        major_brand     : 
            isom
        minor_version   : 
            512
        compatible_brands: 
            isomiso2avc1mp41
        encoder         : 
            Lavf57.25.100
        Duration: 
            00:00:58.82
            , start: 
            0.000000
            , bitrate: 
        7369 kb/s
            Stream #0:0
                (eng)
                    Audio: aac (mp4a / 0x6134706D), 44100 Hz, 2 channels, 160 kb/s
                (default)
            Metadata:
            handler_name    : 
                SoundHandler
            Stream #0:1
                (eng)
                    Video: h264 (avc1 / 0x31637661), none, 640x640, 7213 kb/s

                30 fps, 
                30 tbr, 
                15360 tbn, 
                15360 tbc
                (default)
            Metadata:
            handler_name    : 
            VideoHandler

    ===Ouput Information===

    Audio stream found
    Output #0, adts, to 'out.aac':
        Stream #0:0
    Audio: aac (mp4a / 0x6134706D), 44100 Hz, 2 channels, 160 kb/s

    ==Packet Logging==

    in: pts:-2048 pts_time:-0.0464399 dts:-2048 dts_time:-0.0464399 duration:1024 duration_time:0.02322 stream_index:0
    out: pts:-2048 pts_time:-0.0464399 dts:-2048 dts_time:-0.0464399 duration:1024 duration_time:0.02322 stream_index:0
    in: pts:-1024 pts_time:-0.02322 dts:-1024 dts_time:-0.02322 duration:1024 duration_time:0.02322 stream_index:0
    out: pts:-1024 pts_time:-0.02322 dts:-1024 dts_time:-0.02322 duration:1024 duration_time:0.02322 stream_index:0
    in: pts:0 pts_time:0 dts:0 dts_time:0 duration:1024 duration_time:0.02322 stream_index:0
    out: pts:0 pts_time:0 dts:0 dts_time:0 duration:1024 duration_time:0.02322 stream_index:0
    in: pts:0 pts_time:0 dts:0 dts_time:0 duration:512 duration_time:0.0333333 stream_index:1

Error is 
Signal: SIGSEGV (signal SIGSEGV: invalid address (fault address: 0x29))

I would like to get some help for the last part, how to correctly copy the packets, and also how to not use in_stream->codec->codec,since it is deprecated, but i couldn’t find a way to use with codecpar

Cheers.
David Barishev.


_______________________________________________
Libav-user mailing list
[hidden email]
http://ffmpeg.org/mailman/listinfo/libav-user