ChinaFFmpeg

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 15588|回复: 0

[Linux] 使用FFmpeg将mp4转为ts(代码实现)

[复制链接]
发表于 2014-8-22 13:36:32 | 显示全部楼层 |阅读模式


使用ffmpeg将mp4转为ts的命令格式如下:

[AppleScript] 纯文本查看 复制代码
ffmpeg -i b.mp4 -codec copy -bsf h264_mp4toannexb a.ts


如果不使用-bsf h264_mp4toannexb参数,会提示错误,错误信息如下:

[AppleScript] 纯文本查看 复制代码
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           : bbs.chinaffmpeg.com 孙悟空
    encoder         : Lavf55.49.100
    copyright       :bbs.chinaffmpeg.com 孙悟空
  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           : bbs.chinaffmpeg.com 孙悟空
    copyright       : bbs.chinaffmpeg.com 孙悟空
    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 failed!

从上面的提示纤细可以看到,提示了:

[AppleScript] 纯文本查看 复制代码
[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来进行转换;


下面介绍一下代码实现:

代码实现主要分为三个步骤:
[AppleScript] 纯文本查看 复制代码
1.       初始化filterav_bitstream_filter_init
2.       使用filter转换av_bitstream_filter_filter
3.       关闭filter av_bitstream_filter_close


其他与正常的转封装相同

[C] 纯文本查看 复制代码

#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 bbs.chinaffmpeg.com 孙悟空\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'\n", "./fuck.m3u8");
        return -ENOENT;
    }

    if ((ret = avformat_write_header(output_fmtctx, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Cannot write the header for the file '%s' ret = %d bbs.chinaffmpeg.com 孙悟空\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\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;
                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;

}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|Archiver|ChinaFFmpeg

GMT+8, 2024-4-26 21:45 , Processed in 0.053385 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表