Hi all,

posting here in case someone can provide ideas.

With the attached code I'm able to stream-copy and remux an AAC file
to an MP4.

$ remuxing in.AAC out.mp4

$ mp4info version 2.0.0
out.mp4:
FindBytesProperty: no such property 
moov.trak[0].mdia.minf.stbl.stsd.*[0].*.esds.decConfigDescr.decSpecificInfo[0].info
 (src/mp4file.cpp,865)
Track   Type    Info
1       audio   MPEG-4 Unknown Profile(0), 38.150 secs, 149 kbps, 44100 Hz
 Encoded with: Lavf55.10.101

$ MP4Box -info out.mp4 
* Movie Info *
        Timescale 1000 - Duration 00:00:38.151
        1 track(s)
        Fragmented File: no
        File Brand isom - version 512
        Created: UNKNOWN DATE
File has no MPEG4 IOD/OD

iTunes Info:
        Encoder Software: Lavf55.10.101

Track # 1 Info - TrackID 1 - TimeScale 44100 - Media Duration 00:00:38.150
Track has 1 edit lists: track duration is 00:00:38.151
Media Info: Language "Undetermined" - Type "soun:mp4a" - 1643 samples
MPEG-4 Config: Audio Stream - ObjectTypeIndication 0x40
Corrupted AAC Config
Self-synchronized
Alternate Group ID 1

...

If I convert the file with the command:
$ ffmpeg -i in.aac -c copy -bsf:a aac_adtstoasc -y out2.mp4

$ mp4info out2.mp4 
mp4info version 2.0.0
out2.mp4:
Track   Type    Info
1       audio   MPEG-4 AAC LC, 38.150 secs, 149 kbps, 44100 Hz
 Encoded with: Lavf55.10.101

$ MP4Box -info out2.mp4
* Movie Info *
        Timescale 1000 - Duration 00:00:38.151
        1 track(s)
        Fragmented File: no
        File Brand isom - version 512
        Created: UNKNOWN DATE
File has no MPEG4 IOD/OD

iTunes Info:
        Encoder Software: Lavf55.10.101

Track # 1 Info - TrackID 1 - TimeScale 44100 - Media Duration 00:00:38.150
Track has 1 edit lists: track duration is 00:00:38.151
Media Info: Language "Undetermined" - Type "soun:mp4a" - 1643 samples
MPEG-4 Config: Audio Stream - ObjectTypeIndication 0x40
MPEG-4 Audio AAC LC - 2 Channel(s) - SampleRate 44100
Self-synchronized
Alternate Group ID 1

...

So the problem seems related to the missing profile information.

Help with the issue is very welcome. I plan to send the example for
inclusion once I spot the problem.
/*
 * Copyright (c) 2013 Stefano Sabatini
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * @file
 * libavformat/libavcodec remuxing API example.
 *
 * Output a media file in any supported libavformat format.
 * The default codecs are used.
 * @example doc/examples/remuxing.c
 */

#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>

void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt, const char *tag)
{
    AVRational time_base = fmt_ctx->streams[pkt->stream_index]->time_base;

    printf("%s: pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
           tag,
           av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &time_base),
           av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &time_base),
           av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, &time_base),
           pkt->stream_index);
}

int main(int argc, char **argv)
{
    AVOutputFormat *ofmt = NULL;
    AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL;
    AVStream *out_audio_stream = NULL, *in_audio_stream = NULL;
    AVPacket inpkt;
    const char *in_filename, *out_filename;
    AVBitStreamFilterContext *absf_ctx = NULL;
    int ret;

    if (argc != 3) {
        printf("usage: %s input output\n"
               "API example program to transcode a media file with libavformat and libavcodec.\n"
               "The output format is guessed according to the file extension.\n"
               "\n", argv[0]);
        return 1;
    }

    in_filename  = argv[1];
    out_filename = argv[2];

    av_register_all();

    if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
        fprintf(stderr, "Could not open input file '%s'", in_filename);
        goto end;
    }

    if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
        fprintf(stderr, "Failed to retrieve input stream information");
        goto end;
    }

    ret = av_find_best_stream(ifmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0);
    if (ret >= 0) {
        in_audio_stream = ifmt_ctx->streams[ret];
    } else {
        fprintf(stderr, "No audio in input file, aborting\n");
        goto end;
    }
    av_dump_format(ifmt_ctx, 0, in_filename, 0);

    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename);
    if (!ofmt_ctx) {
        fprintf(stderr, "Could not deduce video output format from file extension.\n");
        ret = AVERROR(ENOMEM);
        goto end;
    }

    ofmt = ofmt_ctx->oformat;

    if (ofmt->audio_codec != AV_CODEC_ID_NONE && in_audio_stream) {
        out_audio_stream = avformat_new_stream(ofmt_ctx, in_audio_stream->codec->codec);
        if (!out_audio_stream) {
            fprintf(stderr, "Failed allocating audio output stream\n");
            ret = AVERROR_UNKNOWN;
            goto end;
        }

        ret = avcodec_copy_context(out_audio_stream->codec, in_audio_stream->codec);
        if (ret < 0) {
            fprintf(stderr, "Failed to copy context from input to output audio\n");
            goto end;
        }
        out_audio_stream->codec->codec_tag = 0;

        if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) {
            out_audio_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
        }
    }
    av_dump_format(ofmt_ctx, 0, out_filename, 1);

    if (!(ofmt->flags & AVFMT_NOFILE)) {
        ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
        if (ret < 0) {
            fprintf(stderr, "Could not open output filename '%s'", out_filename);
            goto end;
        }
    }

    /* create bitstream filter in case of need for converting AAC -> MP4 */
    if (!strcmp(ifmt_ctx->iformat->name, "aac") &&
        (!strcmp(ofmt_ctx->oformat->name, "flv") ||
         !strcmp(ofmt_ctx->oformat->name, "mp4") ||
         !strcmp(ofmt_ctx->oformat->name, "mov"))) {
        const char *absf_name = "aac_adtstoasc";
        printf("Inserting bitsteam filter %s\n", absf_name);
        absf_ctx = av_bitstream_filter_init("aac_adtstoasc");
        if (!absf_ctx) {
            fprintf(stderr, "No available 'aac_adtstoasc' bitstream filter\n");
            ret = AVERROR_BSF_NOT_FOUND;
            goto end;
        }
    }

    ret = avformat_write_header(ofmt_ctx, NULL);
    if (ret < 0) {
        fprintf(stderr, "Error occurred when opening output file\n");
        goto end;
    }

    while (1) {
        ret = av_read_frame(ifmt_ctx, &inpkt);
        if (ret < 0)
            break;

        if (inpkt.stream_index == in_audio_stream->index) {
            /* filter packet if required */
            if (absf_ctx) {
                AVPacket new_inpkt = inpkt;

                ret = av_bitstream_filter_filter(absf_ctx, in_audio_stream->codec, NULL,
                                                 &new_inpkt.data, &new_inpkt.size,
                                                 inpkt.data, inpkt.size,
                                                 inpkt.flags & AV_PKT_FLAG_KEY);
                if (ret < 0) {
                    fprintf(stderr, "Failed to filter bitstream\n");
                    goto end;
                }

                /* create a padded packet */
                if (ret == 0 && new_inpkt.data != inpkt.data && new_inpkt.destruct) {
                    // the new buffer should be a subset of the old so cannot overflow
                    uint8_t *t = av_malloc(new_inpkt.size + FF_INPUT_BUFFER_PADDING_SIZE);
                    if (!t) {
                        ret = AVERROR(ENOMEM);
                        goto end;
                    }
                    memcpy(t, new_inpkt.data, new_inpkt.size);
                    memset(t + new_inpkt.size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
                    new_inpkt.data = t;
                    new_inpkt.buf = NULL;
                }
                av_free_packet(&inpkt);
                new_inpkt.buf = av_buffer_create(new_inpkt.data, new_inpkt.size,
                                                 av_buffer_default_free, NULL, 0);
                if (!new_inpkt.buf) {
                    ret = AVERROR(ENOMEM);
                    goto end;
                }
                inpkt = new_inpkt;
            }

            /* copy packet */
            inpkt.pts = av_rescale_q(inpkt.pts, in_audio_stream->time_base, out_audio_stream->time_base);
            inpkt.dts = av_rescale_q(inpkt.dts, in_audio_stream->time_base, out_audio_stream->time_base);
            inpkt.duration = av_rescale_q(inpkt.duration, in_audio_stream->time_base, out_audio_stream->time_base);
            inpkt.pos = -1;
            inpkt.stream_index = out_audio_stream->index;
            log_packet(ofmt_ctx, &inpkt, "out audio");
            ret = av_interleaved_write_frame(ofmt_ctx, &inpkt);
            if (ret < 0) {
                fprintf(stderr, "Error muxing audio packet\n");
                break;
            }
        }
        av_free_packet(&inpkt);
    }

end:
    av_write_trailer(ofmt_ctx);

    /* close input */
    if (in_audio_stream)
        avcodec_close(in_audio_stream->codec);
    avformat_close_input(&ifmt_ctx);

    /* close output */
    if (out_audio_stream)
        avcodec_close(out_audio_stream->codec);
    if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
        avio_close(ofmt_ctx->pb);
    avformat_free_context(ofmt_ctx);

    if (absf_ctx)
        av_bitstream_filter_close(absf_ctx);

    if (ret < 0 && ret != AVERROR_EOF) {
        fprintf(stderr, "Error occurred: %s\n", av_err2str(ret));
        return 1;
    }

    return 0;
}
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to