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