向mp4容器请求ffmpeg原始数据的示例

时间:2018-10-03 04:05:03

标签: ffmpeg h.264

我有一个包含原始h264数据的二进制文件,其排列方式如下 NAL(SPS),NAL(PPS),NAL(帧),NAL(SPS),NAL(PPS).... 我想将其(无编码)混合到一个mp4容器中。 ffmpeg示例中的muxing.c可以对yuv数据进行编码,但这与我的情况不同,而且我不知道如何更改示例以执行我想做的事情...

我知道命令ffmpeg -i h264file -c复制h264.mp4可以完成我想做的事情,但是我必须在程序中做到这一点,所以我需要知道如何使用ffmpeg api来做到这一点事情,但是到目前为止,我找不到任何简单的例子可以做到这一点。有没有人暗示如何做?谢谢

更新后,我已经从参考文献中编写了以下代码,看来可以创建mp4,但时间不正确,它丢失了帧速率信息和时间信息,播放速度非常快。

av_register_all();

int ret;
AVDictionary *opt = NULL;
//bool is264 = true;
const char * inputFileName = "input.264";
const char * outputFileName = "output.mp4";

AVFormatContext *ic = avformat_alloc_context(); 
if((ret = avformat_open_input(&ic, inputFileName, NULL, NULL)) < 0)
    return -1;//

// Get format info (retrieve stream information)
if ((ret = avformat_find_stream_info(ic, NULL)) < 0)
    return ret; // Couldn't find stream information

for (int i = 0; i < ic->nb_streams; i++) 
{
    AVStream *stream;
    AVCodecContext *codec_ctx;
    stream = ic->streams[i];
    codec_ctx = stream->codec;
    /* Reencode video & audio and remux subtitles etc. */
    if (codec_ctx->codec_type == AVMEDIA_TYPE_VIDEO
        || codec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
        /* Open decoder */
        ret = avcodec_open2(codec_ctx, avcodec_find_decoder(codec_ctx->codec_id), NULL);
        if (ret < 0) {
            //av_log(NULL, AV_LOG_ERROR, "Failed to open decoder for stream #%u\n", i);
            return ret;
        }
    }
}

// Dump information about file onto standard error
av_dump_format(ic, 0, inputFileName, 0);

AVFormatContext *oc;

avformat_alloc_output_context2(&oc, NULL, NULL, outputFileName);
if (!oc) {
    //printf("Could not deduce output format from file extension: using MPEG.\n");
    //avformat_alloc_output_context2(&oc, NULL, "mpeg", outputFileName);
    return -1;
}

AVStream *ist = ic->streams[0];

AVCodec *out_vid_codec = avcodec_find_encoder(oc->oformat->video_codec);
if (NULL == out_vid_codec)
    return -1;  // Couldn't find video encoder

AVStream *out_vid_strm = avformat_new_stream(oc, out_vid_codec);
if (NULL == out_vid_strm)
    return -1;  // Couldn't output video stream

ret = avcodec_copy_context(out_vid_strm->codec, ist->codec);
if (ret < 0)
    return ret;  // Failed to copy context

ret = avio_open(&oc->pb, outputFileName, AVIO_FLAG_WRITE);
ret = avformat_write_header(oc, NULL);

AVPacket pkt;   

while(1)
{           
    AVStream *in_stream, *out_stream;
    ret = av_read_frame(ic, &pkt);
    if (ret < 0)
        break;

    pkt.stream_index = 0;
    in_stream = ic->streams[pkt.stream_index];
    out_stream = oc->streams[pkt.stream_index];


    pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
    pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (AVRounding)(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;
    //log_packet(ofmt_ctx, &pkt, "out");

    ret = av_interleaved_write_frame(oc, &pkt);
    if (ret < 0) {
        fprintf(stderr, "Error muxing packet\n");
        break;
    }
    av_packet_unref(&pkt);
}

av_write_trailer(oc);

0 个答案:

没有答案