FFmpeg之从MP4提取H264裸流


// mp4 转 h264 裸码流
ffmpeg -i input.mp4 -vcodec h264 output.h264
// Video: h264, yuv420p(tv, bt709, progressive)
ffmpeg.exe -i input.mp4 -color_primaries bt709 -color_trc bt709 -colorspace bt709 output.h264
// Video: h264, yuv420p(progressive)
ffmpeg -i input_file.avi -vcodec copy -an -bsf:v h264_mp4toannexb output_file.h264

#ifndef DECODER_H
#define DECODER_H

#include <iostream>
#include <QDebug>
#include <QRunnable>
#include <QThread>

extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/imgutils.h"
}

class Decoder : public QRunnable
{
public:
    Decoder();
    ~Decoder();
    void run();
    bool create();
private:
    Log4Qt::Logger *m_log;
    AVFormatContext *pFormatCtx;
    AVBitStreamFilterContext* h264bsfc;
    int videoindex;
};
#endif // DECODER_H
#include "decoder.h"

Decoder::Decoder()
{
}

Decoder::~Decoder()
{
}

bool Decoder::create()
{
    // qDebug() << avcodec_configuration();
    Runtime::m_decoder_mutex.lock();

    av_register_all();
    avformat_network_init();

    pFormatCtx = avformat_alloc_context();

    if(avformat_open_input(&pFormatCtx, "E:/1111.mp4", NULL, NULL) != 0){
    printf("Couldn't open input stream.\n");
    return false;
    }

    if(avformat_find_stream_info(pFormatCtx, NULL) < 0){
    printf("Couldn't find stream information.\n");
    return false;
    }

    videoindex = -1;
    for(int i = 0; i < pFormatCtx->nb_streams; i++) {
    if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
        videoindex = i;
        break;
    }
    }
    if(videoindex == -1) {
    printf("Didn't find a video stream.\n");
    return false;
    }

    h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
    if(h264bsfc == NULL) {
    printf("h264bsfc not found.\n");
    return false;
    }

    // --------------------------------- //
    AVCodec* currentCodec = NULL;
    currentCodec = av_codec_next(currentCodec);
    while (currentCodec != NULL) {
    if (av_codec_is_encoder(currentCodec)) {
        cout << currentCodec->name << "\t" << currentCodec->long_name << endl;
    }
    currentCodec = av_codec_next(currentCodec);
    }
    // --------------------------------- //

    Runtime::m_decoder_mutex.unlock();
    return true;
}

#ifdef Q_OS_LINUX // Linux

#endif

#ifdef Q_OS_WIN // Windows 10

void Decoder::run()
{

    this->create();

    AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));

    FILE *fp=fopen("test.264","ab");

    int count = 0;
    while(av_read_frame(pFormatCtx, packet) >= 0)
    {
    av_bitstream_filter_filter(h264bsfc, pFormatCtx->streams[videoindex]->codec, NULL, &packet->data, &packet->size, packet->data, packet->size, 0);
    fwrite(packet->data, 1, packet->size, fp);
    count++;
    av_free_packet(packet);
    }

    av_bitstream_filter_close(h264bsfc);
    avformat_close_input(&pFormatCtx);

}

#endif