FFmpeg In Android
阿新 • • 發佈:2018-12-17
FFmpeg很龐大,可以參考上面的連結,csdn上雷霄驊的部落格,稍微熟悉點後可以看官方自帶的例子,ffmpeg-3.3.8/doc/examples,通過例子熟悉FFmpeg的流程和函式.不過看了很多例子都是FFmpeg+SDL的,實際上Android開發者真的需要用SDL嗎,渲染部分用Android平臺自身的功能還更容易上手,SDL等熟悉FFmpeg了再進行研究吧.
這個例子說明了怎樣使用ffmpeg進行多媒體檔案的解封裝,解碼成Yuv420p,並儲存為檔案.然後可以用Yuv播放器播放該檔案. 流程圖如下,圖片來源: 函式說明(注意隨著ffmpeg的版本不同,流程圖上的函式名可能不同了):
/** * Initialize libavformat and register all the muxers, demuxers and * protocols. If you do not call this function, then you can select * exactly which formats you want to support. * * @see av_register_input_format() * @see av_register_output_format() */ void av_register_all(void); 註冊了所有的檔案格式和編解碼器的庫, 也可以只註冊特定的格式和編解碼器:av_register_input_format(), av_register_output_format()
/** * Open an input stream and read the header. The codecs are not opened. * The stream must be closed with avformat_close_input(). * * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). * May be a pointer to NULL, in which case an AVFormatContext is allocated by this * function and written into ps. * Note that a user-supplied AVFormatContext will be freed on failure. * @param url URL of the stream to open. * @param fmt If non-NULL, this parameter forces a specific input format. * Otherwise the format is autodetected. * @param options A dictionary filled with AVFormatContext and demuxer-private options. * On return this parameter will be destroyed and replaced with a dict containing * options that were not found. May be NULL. * * @return 0 on success, a negative AVERROR on failure. * * @note If you want to use custom IO, preallocate the format context and set its pb field. */ int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options); 讀取檔案的頭部並且把資訊儲存到第一個引數AVFormatContext結構體中。 最後三個引數用來指定特殊的檔案格式,緩衝大小和格式引數,但如果把它們設定為空 NULL 或者 0,將自動檢測這些引數。
/** * Read packets of a media file to get stream information. This * is useful for file formats with no headers such as MPEG. This * function also computes the real framerate in case of MPEG-2 repeat * frame mode. * The logical file position is not changed by this function; * examined packets may be buffered for later processing. * * @param ic media file handle * @param options If non-NULL, an ic.nb_streams long array of pointers to * dictionaries, where i-th member contains options for * codec corresponding to i-th stream. * On return each dictionary will be filled with options that were not found. * @return >=0 if OK, AVERROR_xxx on error * * @note this function isn't guaranteed to open all the codecs, so * options being non-empty at return is a perfectly normal behavior. * * @todo Let the user decide somehow what information is needed so that * we do not waste time getting stuff the user does not need. */ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options); avformat_open_input函式只是檢測了檔案的頭部,這個函式檢查在檔案中的流的資訊
/**
* Find the "best" stream in the file.
* The best stream is determined according to various heuristics as the most
* likely to be what the user expects.
* If the decoder parameter is non-NULL, av_find_best_stream will find the
* default decoder for the stream's codec; streams for which no decoder can
* be found are ignored.
*
* @param ic media file handle
* @param type stream type: video, audio, subtitles, etc.
* @param wanted_stream_nb user-requested stream number,
* or -1 for automatic selection
* @param related_stream try to find a stream related (eg. in the same
* program) to this one, or -1 if none
* @param decoder_ret if non-NULL, returns the decoder for the
* selected stream
* @param flags flags; none are currently defined
* @return the non-negative stream number in case of success,
* AVERROR_STREAM_NOT_FOUND if no stream with the requested type
* could be found,
* AVERROR_DECODER_NOT_FOUND if streams were found but no decoder
* @note If av_find_best_stream returns successfully and decoder_ret is not
* NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.
*/
int av_find_best_stream(AVFormatContext *ic,
enum AVMediaType type,
int wanted_stream_nb,
int related_stream,
AVCodec **decoder_ret,
int flags);
找到視訊流或音訊流的索引,其中包含編解碼器的資訊
/**
* Find a registered decoder with a matching codec ID.
*
* @param id AVCodecID of the requested decoder
* @return A decoder if one was found, NULL otherwise.
*/
AVCodec *avcodec_find_decoder(enum AVCodecID id);
找到編解碼器
/**
* Allocate an AVCodecContext and set its fields to default values. The
* resulting struct should be freed with avcodec_free_context().
*
* @param codec if non-NULL, allocate private data and initialize defaults
* for the given codec. It is illegal to then call avcodec_open2()
* with a different codec.
* If NULL, then the codec-specific defaults won't be initialized,
* which may result in suboptimal default settings (this is
* important mainly for encoders, e.g. libx264).
*
* @return An AVCodecContext filled with default values or NULL on failure.
*/
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);
流中關於編解碼器的資訊就是被我們叫做“編解碼器上下文”(codec context)的東西。這裡麵包含了流中所
使用的關於編解碼器的所有資訊,現在我們有了一個指向它的指標.
int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);
開啟編碼器
/**
* Allocate an AVFrame and set its fields to default values. The resulting
* struct must be freed using av_frame_free().
*
* @return An AVFrame filled with default values or NULL on failure.
*
* @note this only allocates the AVFrame itself, not the data buffers. Those
* must be allocated through other means, e.g. with av_frame_get_buffer() or
* manually.
*/
AVFrame *av_frame_alloc(void);
分配一個AVFrame並設為預設值,用來存放幀資料
int av_read_frame(AVFormatContext *s, AVPacket *pkt);
從流中讀取一幀完整資料或者多幀完整(ffmpeg內部保證了完整性)
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
const AVPacket *avpkt);
解碼原始流中的一幀資料(輸出yuv資料)
/**
* Copy image in src_data to dst_data.
*
* @param dst_linesizes linesizes for the image in dst_data
* @param src_linesizes linesizes for the image in src_data
*/
void av_image_copy(uint8_t *dst_data[4], int dst_linesizes[4],
const uint8_t *src_data[4], const int src_linesizes[4],
enum AVPixelFormat pix_fmt, int width, int height);
拷貝圖片資料