使用ffmpeg存为avi和存为mp4在代码上是一样的,ffmpeg可以通过文件名后缀决定视频文件类型,以下是关键代码:
AviWriter.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #pragma once class AVFormatContext; class AVStream; class AviWriter { public: int createFile(const char* filename); int setVideoTrack(const char* sps, int spslen, const char* pps, int ppslen, int width, int hight, int rate); int writeVideoSample(char* data, int datasize, bool keyframe); void closeFile(); private: AVFormatContext *m_fc; AVStream *m_avStream; int m_isHeaderWritten; }; |
AviWriter.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | #include "AviWriter.h" #include <string> #ifdef __cplusplus extern "C" { #endif #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #ifdef __cplusplus } #endif using namespace std; int AviWriter::createFile(const char* filename) { string aviFileName = filename; aviFileName = aviFileName.substr(0, aviFileName.length() - strlen(".avi")) + ".avi"; m_isHeaderWritten = 0; av_log_set_level(AV_LOG_QUIET); av_register_all(); avformat_network_init(); avformat_alloc_output_context2(&m_fc, NULL, NULL, aviFileName.c_str()); m_avStream = avformat_new_stream(m_fc, NULL); AVCodecContext *c; c = m_avStream->codec; c->codec_type = AVMEDIA_TYPE_VIDEO; c->codec_id = AV_CODEC_ID_H264; c->width = 1920; c->height = 1080; c->pix_fmt = AV_PIX_FMT_YUV420P; c->time_base.den = 25; c->time_base.num = 1; c->extradata = NULL; if (avio_open(&m_fc->pb, m_fc->filename, 2) < 0) return -1; return 0; } int AviWriter::setVideoTrack(const char* sps, int spslen, const char* pps, int ppslen, int width, int hight, int rate) { unsigned char splitter[4] = { 0, 0, 0, 1 }; int extraSize = 4 + spslen + 4 + ppslen + FF_INPUT_BUFFER_PADDING_SIZE; AVCodecContext *c; c = m_avStream->codec; av_free(c->extradata); c->extradata = (unsigned char *)av_malloc(extraSize); memcpy(c->extradata, splitter, 4); memcpy(c->extradata + 4, sps, spslen); memcpy(c->extradata + 4 + spslen, splitter, 4); memcpy(c->extradata + 4 + spslen + 4, pps, ppslen); c->extradata_size = 4 + spslen + 4 + ppslen; m_isHeaderWritten = 1; if (avformat_write_header(m_fc, NULL) != 0) return -1; return 0; } int AviWriter::writeVideoSample(char* data, int datasize, bool keyframe) { if (NULL == m_fc || NULL == m_avStream) return -1; AVPacket pkt; av_init_packet(&pkt); pkt.stream_index = m_avStream->index; pkt.data = (unsigned char *)data; pkt.size = datasize; pkt.flags = keyframe ? AV_PKT_FLAG_KEY : 0; av_interleaved_write_frame(m_fc, &pkt); av_free_packet(&pkt); return 0; } void AviWriter::closeFile() { if (NULL == m_fc) return; if (m_isHeaderWritten) av_write_trailer(m_fc); avio_close(m_fc->pb); avformat_free_context(m_fc); m_fc = NULL; } |