- ffmpeg -i b.mp4 -codec copy -bsf h264_mp4toannexb a.ts
如果不使用-bsf h264_mp4toannexb参数,会提示错误,错误信息如下:
- ffmpeg -i b.mp4 -codec copy a.ts
- ffmpeg version N-65108-gf2855eb Copyright (c) 2000-2014 the FFmpeg developers
- built on Jul 31 2014 02:29:27 with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-4)
- configuration: --prefix=/usr/local --enable-gpl --enable-nonfree --enable-libfaac --enable-libfreetype --enable-libx264 --enable-libx265
- libavutil 52. 93.100 / 52. 93.100
- libavcodec 55. 71.100 / 55. 71.100
- libavformat 55. 49.100 / 55. 49.100
- libavdevice 55. 13.102 / 55. 13.102
- libavfilter 4. 11.102 / 4. 11.102
- libswscale 2. 6.100 / 2. 6.100
- libswresample 0. 19.100 / 0. 19.100
- libpostproc 52. 3.100 / 52. 3.100
- Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'b.mp4':
- Metadata:
- major_brand : isom
- minor_version : 512
- compatible_brands: isomiso2avc1mp41
- title : ????????
- encoder : Lavf55.49.100
- copyright : (C) 2004 HFD2B
- Duration: 00:04:09.44, start: 0.000000, bitrate: 568 kb/s
- Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 592x336, 436 kb/s, 23.98 fps, 23.98 tbr, 785647.00 tbn, 47.95 tbc (default)
- Metadata:
- handler_name : VideoHandler
- Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 127 kb/s (default)
- Metadata:
- handler_name : SoundHandler
- File 'a.ts' already exists. Overwrite ? [y/N] y
- [adts @ 0x2269660] Using AVStream.codec.time_base as a timebase hint to the muxer is deprecated. Set AVStream.time_base instead.
- Output #0, mpegts, to 'a.ts':
- Metadata:
- major_brand : isom
- minor_version : 512
- compatible_brands: isomiso2avc1mp41
- title : ????????
- copyright : (C) 2004 HFD2B
- encoder : Lavf55.49.100
- Stream #0:0(und): Video: h264 (avc1 / 0x31637661), yuv420p, 592x336, q=2-31, 436 kb/s, 23.98 fps, 90k tbn, 23.98 tbc (default)
- Metadata:
- handler_name : VideoHandler
- Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, 127 kb/s (default)
- Metadata:
- handler_name : SoundHandler
- Stream mapping:
- Stream #0:0 -> #0:0 (copy)
- Stream #0:1 -> #0:1 (copy)
- Press [q] to stop, [?] for help
- [mpegts @ 0x22761a0] H.264 bitstream malformed, no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)
- av_interleaved_write_frame(): Invalid argument
- frame= 1 fps=0.0 q=-1.0 Lsize= 1kB time=00:00:00.04 bitrate= 216.3kbits/s
- video:1kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
- Conversion
从上面的提示纤细可以看到,提示了:
[mpegts @ 0x22761a0] H.264 bitstream malformed, no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)
av_interleaved_write_frame(): Invalid argument
主要是因为使用了mp4中的h264编码,而h264有两种封装:
一种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中;另一种是mp4模式,一般mp4、mkv、avi会没有startcode,SPS和PPS以及其它信息被封装在container中,每一个frame前面是这个frame的长度,很多解码器只支持annexb这种模式,因此需要将mp4做转换;在ffmpeg中用h264_mp4toannexb_filter可以做转换;所以需要使用-bsf h264_mp4toannexb来进行转换;
下面介绍一下代码实现:
代码实现主要分为三个步骤:
[mpegts @ 0x22761a0] H.264 bitstream malformed, no startcode found, use the h264_mp4toannexb bitstream filter (-bsf h264_mp4toannexb)
av_interleaved_write_frame(): Invalid argument
主要是因为使用了mp4中的h264编码,而h264有两种封装:
一种是annexb模式,传统模式,有startcode,SPS和PPS是在ES中;另一种是mp4模式,一般mp4、mkv、avi会没有startcode,SPS和PPS以及其它信息被封装在container中,每一个frame前面是这个frame的长度,很多解码器只支持annexb这种模式,因此需要将mp4做转换;在ffmpeg中用h264_mp4toannexb_filter可以做转换;所以需要使用-bsf h264_mp4toannexb来进行转换;
下面介绍一下代码实现:
代码实现主要分为三个步骤:
- 1. 初始化filterav_bitstream_filter_init
- 2. 使用filter转换av_bitstream_filter_filter
- 3. 关闭filter av_bitstream_filter_close
其他与正常的转封装相同
点击(此处)折叠或打开
- #include <stdio.h>
- #include <stdlib.h>
- #include <libavformat/avformat.h>
- #include <libavutil/avutil.h>
-
- #define FORMAT "mpegts"
- #define OUTPUT_FILE "./fuck.ts"
- #define INPUT_FILE "./a.avi"
-
- int main(int argc, char *argv[])
- {
- AVPacket pkt;
- AVFormatContext *input_fmtctx = NULL;
- AVFormatContext *output_fmtctx = NULL;
- AVCodecContext *enc_ctx = NULL;
- AVCodecContext *dec_ctx = NULL;
- AVCodec *encoder = NULL;
- AVBitStreamFilterContext * vbsf = NULL;
- int ret = 0;
- int i = 0;
- int have_key = 0;
- static int first_pkt = 1;
-
- av_register_all();
-
- if (avformat_open_input(&input_fmtctx, INPUT_FILE, NULL, NULL) < 0) {
- av_log(NULL, AV_LOG_ERROR, "Cannot open the file %s\n", "./a.mp4");
- return -ENOENT;
- }
-
- if (avformat_find_stream_info(input_fmtctx,0) < 0) {
- av_log(NULL, AV_LOG_ERROR, "bbs.chinaffmpeg.com 孙悟空 Failed to retrieve input stream information\n");
- return -EINVAL;
- }
-
- av_dump_format(input_fmtctx, NULL, INPUT_FILE, 0);
-
- if (avformat_alloc_output_context2(&output_fmtctx, NULL, FORMAT, OUTPUT_FILE) < 0) {
- av_log(NULL, AV_LOG_ERROR, "Cannot open the file %s bbs.chinaffmpeg.com 孙悟空\n", OUTPUT_FILE);
- return -ENOENT;
- }
-
- /* Process transcode parameters */
- for (i = 0; i < input_fmtctx->nb_streams; i++) {
- AVStream *out_stream = NULL;
- AVStream *in_stream = NULL;
-
- in_stream = input_fmtctx->streams[i];
- out_stream = avformat_new_stream(output_fmtctx, in_stream->codec->codec);
- if (out_stream < 0) {
- av_log(NULL, AV_LOG_ERROR, "bbs.chinaffmpeg.com 孙悟空 Alloc new Stream error\n");
- return -EINVAL;
- }
-
- avcodec_copy_context(output_fmtctx->streams[i]->codec, input_fmtctx->streams[i]->codec);
-
- out_stream->codec->codec_tag = 0;
- if (output_fmtctx->oformat->flags & AVFMT_GLOBALHEADER) {
- out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
- }
- }
-
- vbsf = av_bitstream_filter_init("h264_mp4toannexb");
-
-
- av_dump_format(output_fmtctx, NULL, OUTPUT_FILE, 1);
-
- if (avio_open2(&output_fmtctx->pb, OUTPUT_FILE, AVIO_FLAG_WRITE, &output_fmtctx->interrupt_callback, NULL) < 0) {
- av_log(NULL, AV_LOG_ERROR, "cannot open the output file '%s' bbs.chinaffmpeg.com 孙悟空\n", "./fuck.m3u8");
- return -ENOENT;
- }
-
- av_opt_set(output_fmtctx->priv_data, "hls_time", "10");
-
- if ((ret = avformat_write_header(output_fmtctx, NULL)) < 0) {
- av_log(NULL, AV_LOG_ERROR, "bbs.chinaffmpeg.com 孙悟空 Cannot write the header for the file '%s' ret = %d\n", "fuck.ts", ret);
- return -ENOENT;
- }
-
- while (1) {
- AVStream *in_stream = NULL;
- AVStream *out_stream = NULL;
-
- ret = av_read_frame(input_fmtctx, &pkt);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "read frame error %d bbs.chinaffmpeg.com 孙悟空\n", ret);
- break;
- }
-
- if (pkt.pts == AV_NOPTS_VALUE && first_pkt) {
- pkt.pts = pkt.dts;
- first_pkt = 0;
- }
-
- in_stream = input_fmtctx->streams[pkt.stream_index];
- out_stream = output_fmtctx->streams[pkt.stream_index];
-
- pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
- pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
- pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
- pkt.pos = -1;
-
- if (pkt.stream_index == 0) {
-
- AVPacket fpkt = pkt;
- int a = av_bitstream_filter_filter(vbsf,
- out_stream->codec, NULL, &fpkt.data, &fpkt.size,
- pkt.data, pkt.size, pkt.flags & AV_PKT_FLAG_KEY);
- pkt.data = fpkt.data;
- pkt.size = fpkt.size;
-
- }
-
- ret = av_write_frame(output_fmtctx, &pkt);
- if (ret < 0) {
- av_log(NULL, AV_LOG_ERROR, "bbs.chinaffmpeg.com 孙悟空 Muxing Error\n");
- break;
- }
-
- av_free_packet(&pkt);
- }
-
- av_write_trailer(output_fmtctx);
- avformat_close_input(&input_fmtctx);
- avio_close(output_fmtctx->pb);
- avformat_free_context(output_fmtctx);
- av_bitstream_filter_close(vbsf);
- vbsf = NULL;
-
- return 0;
- }