[Libav-user] Copying audio stream
David Barishev
david7815 at gmail.com
Mon Mar 27 23:17:46 EEST 2017
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://ffmpeg.org/pipermail/libav-user/attachments/20170327/8b062b94/attachment.html>
More information about the Libav-user
mailing list