Запрос необработанных данных ffmpeg в пример контейнера mp4 - PullRequest
0 голосов
/ 03 октября 2018

У меня есть двоичный файл с необработанными данными h264, который упорядочен следующим образом: NAL (SPS), NAL (PPS), NAL (кадр), NAL (SPS), NAL (PPS) .... и я хочу мультиплексироватьэто (без кодирования) в контейнер mp4.Файл muxing.c в примере ffmpeg выполняет кодировку данных yuv, но он отличается от моего случая, и у меня нет идей, как изменить пример, чтобы сделать то, что я хочу сделать ...

Iзнал, что запрограммированный ffmpeg -i h264file -c copy h264.mp4 может делать то, что я хочу, но я должен делать это в своей программе, поэтому мне нужно знать, как использовать API ffmpeg для того же, но такпока я не могу найти простой пример, чтобы сделать это.Есть у кого-нибудь подсказка как это сделать ??Спасибо

Обновлено, я написал код, приведенный ниже, из ссылки, кажется, может создать 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);
...