The simplest example of memory read/write based on FFmpeg: Memory Transcoder and ffmpeg read/write
The previous article recorded a memory Player Based on FFmpeg, which can be used to read and play data in the memory. This article records a memory Transcoder Based on FFmpeg. The Transcoder can use FFmpeg to read data in the memory. After transcoding to H.264, the data is output to the memory.
For details about how to read data from the memory and output data to the memory, refer:
Ffmpeg reads data from memory (or outputs data to memory)
There are two key points for FFmpeg read/write memory:
1. initialize the custom AVIOContext and specify the custom callback function.
2. Write the callback function by yourself. Pay attention to the parameters and return values of the function (especially the return values ).
Transcoding is actually a combination of decoding and encoding. For more information, see:
Decoding: 100 lines of code is the simplest Video Player (SDL1.x) based on FFMPEG + SDL)
Encoding: the simplest Video Encoder Based on FFMPEG (YUV encoding: H.264)
Transcoding: the simplest FFMPEG-based transcoding Program
Shows the flowchart of the process program. We can see that AVFormatContext of input and output is initialized respectively. Then, decode the input AVPacket to obtain the AVFrame that stores the pixel data (YUV420P format), encode the AVFrame as the AVPacket of H.264, and output the encoded AVPacket.
Directly paste the code below:
/*** The Simplest example of memory read/write based on FFmpeg (memory Transcoder) ** Simplest FFmpeg mem Transcoder, zhang Hui * leixiaohua1020@126.com * China Communications University/Digital television Technology * Communication University of China/Digital TV Technology * http://blog.csdn.net/leixiaohua1020 ** this program realizes the arbitrary format of video data (such as MPEG2) transcoding to H. 264 bitstream data. * This program does not process files, but video data in the memory. * It reads data from the memory and outputs The transcoded data to the memory. * Is the simplest example of using FFmpeg to read and write memory. ** This software convert video bitstream (Such as MPEG2) to H. 264 * bitstream. it read video bitstream from memory (not from a file), * convert it to H. 264 bitstream, and finally output to another memory. * It's the simplest example to use FFmpeg to read (or write) from * memory. **/# include <stdio. h> extern "C" {# include "libavcodec/avcodec. h "# include" libavformat/avformat. h "# include" libavutil/ Vutil. h "# include" libavutil/opt. h "# include" libavutil/pixdesc. h "}; FILE * fp_open; FILE * fp_write; // Read Fileint read_buffer (void * opaque, uint8_t * buf, int buf_size) {if (! Feof (fp_open) {int true_size = fread (buf, 1, buf_size, fp_open); return true_size;} else {return-1 ;}} // Write Fileint write_buffer (void * opaque, uint8_t * buf, int buf_size) {if (! Feof (fp_write) {int true_size = fwrite (buf, 1, buf_size, fp_write); return true_size;} else {return-1 ;}} int flush_encoder (AVFormatContext * fmt_ctx, unsigned int stream_index) {int ret; int got_frame; AVPacket enc_pkt; if (! (Fmt_ctx-> streams [stream_index]-> codec-> capabilities & CODEC_CAP_DELAY) return 0; while (1) {av_log (NULL, AV_LOG_INFO, "Flushing stream # % u encoder \ n", stream_index); // ret = encode_write_frame (NULL, stream_index, & got_frame); enc_pkt.data = NULL; enc_pkt.size = 0; av_init_packet (& enc_pkt); ret = avcodec_encode_video2 (fmt_ctx-> streams [stream_index]-> codec, & enc_pkt, NULL, & got_frame); av_frame _ Free (NULL); if (ret <0) break; if (! Got_frame) {ret = 0; break;}/* prepare packet for muxing */enc_pkt.stream_index = stream_index; enc_pkt.dts = av_rescale_q_rnd (enc_pkt.dts, fmt_ctx-> streams [stream_index]-> codec-> time_base, fmt_ctx-> streams [stream_index]-> time_base, (AVRounding) (Bytes | AV_ROUND_PASS_MINMAX )); enc_pkt.pts = av_rescale_q_rnd (enc_pkt.pts, fmt_ctx-> streams [stream_index]-> codec-> time_base, fmt_ctx-> streams [stream_index] -> Time_base, (AVRounding) (latency | latency); enc_pkt.duration = av_rescale_q (enc_pkt.duration, fmt_ctx-> streams [stream_index]-> codec-> time_base, fmt_ctx-> streams [stream_index]-> time_base); av_log (NULL, AV_LOG_DEBUG, "Muxing frame \ n");/* mux encoded frame */ret = av_write_frame (fmt_ctx, & enc_pkt); if (ret <0) break;} return ret;} int main (int argc, char * argv []) {int ret; AVFormatCo Ntext * ifmt_ctx = NULL; AVFormatContext * ofmt_ctx = NULL; AVPacket packet, enc_pkt; AVFrame * frame = NULL; enum AVMediaType type; unsigned int stream_index; unsigned int I = 0; int got_frame, enc_got_frame; AVStream * out_stream; AVStream * in_stream; AVCodecContext * dec_ctx, * enc_ctx; AVCodec * encoder; fp_open = fopen ("cuc60anniversary_start.ts", "rb "); // video source file fp_write = fopen ("cuc60anniversary_start.h264", "wb +"); // output file Av_register_all (); ifmt_ctx = avformat_alloc_context (); struct (& ofmt_ctx, NULL, "h264", NULL); unsigned char * inbuffer = NULL; unsigned char * outbuffer = NULL; inbuffer = (unsigned char *) av_malloc (32768); outbuffer = (unsigned char *) av_malloc (32768);/* open input file */AVIOContext * avio_in = avio_alloc_context (inbuffer, 32768,0, NULL, read_buffer, NULL, NULL); if (avio_in = NULL) goto end; ifmt_ctx -> Pb = avio_in; ifmt_ctx-> flags = AVFMT_FLAG_CUSTOM_IO; if (ret = avformat_open_input (& ifmt_ctx, "whatever", NULL, NULL) <0) {av_log (NULL, AV_LOG_ERROR, "Cannot open input file \ n"); return ret;} if (ret = avformat_find_stream_info (ifmt_ctx, NULL) <0) {av_log (NULL, AV_LOG_ERROR, "Cannot find stream information \ n"); return ret;} for (I = 0; I <ifmt_ctx-> nb_streams; I ++) {AVStream * stream; AVCodecContex T * codec_ctx; stream = ifmt_ctx-> streams [I]; codec_ctx = stream-> codec;/* Reencode video & audio and remux subtitles etc. */if (codec_ctx-> codec_type = AVMEDIA_TYPE_VIDEO) {/* 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 ;}}} // av_dump_format (ifmt_ctx, 0 ," Whatever ", 0);/* open output file */AVIOContext * avio_out = avio_alloc_context (outbuffer, 32768,0, NULL, NULL, write_buffer, NULL); if (avio_out = NULL) goto end; // avio_out-> write_packet = write_packet; ofmt_ctx-> pb = avio_out; ofmt_ctx-> flags = AVFMT_FLAG_CUSTOM_IO; for (I = 0; I <1; I ++) {out_stream = avformat_new_stream (ofmt_ctx, NULL); if (! Out_stream) {av_log (NULL, AV_LOG_ERROR, "Failed allocating output stream \ n"); return AVERROR_UNKNOWN;} in_stream = ifmt_ctx-> streams [I]; dec_ctx = in_stream-> codec; enc_ctx = out_stream-> codec; if (dec_ctx-> codec_type = AVMEDIA_TYPE_VIDEO) {encoder = avcodec_find_encoder (AV_CODEC_ID_H264); enc_ctx-> height = dec_ctx-height>; enc_ctx-> width = dec_ctx-> width; enc_ctx-> sample_aspect_ratio = dec_ctx-> sample_asp Ect_ratio; enc_ctx-> pix_fmt = encoder-> pix_fmts [0]; enc_ctx-> time_base = dec_ctx-> time_base; // enc_ctx-> time_base.num = 1; // enc_ctx-> time_base.den = 25; // a required option for H264. If not, the error enc_ctx-> me_range = 16; enc_ctx-> max_qdiff = 4 is returned; enc_ctx-> qmin = 10; enc_ctx-> qmax = 51; enc_ctx-> qcompress = 0.6; enc_ctx-> refs = 3; enc_ctx-> bit_rate = 500000; ret = avcodec_open2 (enc_ctx, encoder, NULL); if (ret <0) {av_log (NULL, AV_LOG_ERROR, "Cannot open video encoder for stream # % u \ n", I); return ret ;}} else if (dec_ctx-> codec_type = AVMEDIA_TYPE_UNKNOWN) {av_log (NULL, AV_LOG_FATAL, "Elementary stream # % d is of unknown type, cannot proceed \ n", I); return AVERROR_INVALIDDATA ;} else {/* if this stream must be remuxed */ret = avcodec_copy_context (ofmt_ctx-> streams [I]-> codec, ifmt_ctx-> streams [I]-> codec ); if (ret <0) {av_log (NULL, AV_LOG _ ERROR, "Copying stream context failed \ n"); return ret ;}}if (ofmt_ctx-> oformat-> flags & AVFMT_GLOBALHEADER) enc_ctx-> flags | = CODEC_FLAG_GLOBAL_HEADER ;} // av_dump_format (ofmt_ctx, 0, "whatever", 1);/* init muxer, write output file header */ret = avformat_write_header (ofmt_ctx, NULL ); if (ret <0) {av_log (NULL, AV_LOG_ERROR, "Error occurred when opening output file \ n"); return ret;} I = 0;/* read all packet S */while (1) {I ++; if (ret = av_read_frame (ifmt_ctx, & packet) <0) break; stream_index = packet. stream_index; if (stream_index! = 0) continue; type = ifmt_ctx-> streams [packet. stream_index]-> codec-> codec_type; av_log (NULL, AV_LOG_DEBUG, "Demuxer gave frame of stream_index % u \ n", stream_index); av_log (NULL, AV_LOG_DEBUG, "Going to reencode the frame \ n"); frame = av_frame_alloc (); if (! Frame) {ret = AVERROR (ENOMEM); break;} packet. dts = av_rescale_q_rnd (packet. dts, ifmt_ctx-> streams [stream_index]-> time_base, ifmt_ctx-> streams [stream_index]-> codec-> time_base, (AVRounding) (Bytes | AV_ROUND_PASS_MINMAX); packet. pts = av_rescale_q_rnd (packet. pts, ifmt_ctx-> streams [stream_index]-> time_base, ifmt_ctx-> streams [stream_index]-> codec-> time_base, (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PA SS_MINMAX); ret = avcodec_decode_video2 (ifmt_ctx-> streams [stream_index]-> codec, frame, & got_frame, & packet); printf ("Decode 1 Packet \ tsize: % d \ tpts: % d \ n ", packet. size, packet. pts); if (ret <0) {av_frame_free (& frame); av_log (NULL, AV_LOG_ERROR, "Decoding failed \ n"); break;} if (got_frame) {frame-> pts = av_frame_get_best_effort_timestamp (frame); frame-> pict_type = AV_PICTURE_TYPE_NONE; enc_pkt.data = NULL; enc_p Kt. size = 0; av_init_packet (& enc_pkt); ret = avcodec_encode_video2 (ofmt_ctx-> streams [stream_index]-> codec, & enc_pkt, frame, & enc_got_frame ); printf ("Encode 1 Packet \ tsize: % d \ tpts: % d \ n", enc_pkt.size, enc_pkt.pts); av_frame_free (& frame); if (ret <0) goto end; if (! Enc_got_frame) continue;/* prepare packet for muxing */bytes = stream_index; enc_pkt.dts = bytes (enc_pkt.dts, ofmt_ctx-> streams [stream_index]-> codec-> time_base, ofmt_ctx-> streams [stream_index]-> time_base, (AVRounding) (AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); enc_pkt.pts = av_rescale_q_rnd (enc_pkt.pts, ofmt_ctx-> streams [stream_index]-> codec-> time_base, ofmt_ctx-> streams [stream_ind Ex]-> time_base, (AVRounding) (events | events); enc_pkt.duration = av_rescale_q (enc_pkt.duration, ofmt_ctx-> streams [stream_index]-> codec-> time_base, ofmt_ctx-> streams [stream_index]-> time_base); av_log (NULL, AV_LOG_INFO, "Muxing frame % d \ n", I ); /* mux encoded frame */av_write_frame (ofmt_ctx, & enc_pkt); if (ret <0) goto end;} else {av_frame_free (& frame );} av_free_packet (& packet);}/* fl Ush encoders */for (I = 0; I <1; I ++) {/* flush encoder */ret = flush_encoder (ofmt_ctx, I); if (ret <0) {av_log (NULL, AV_LOG_ERROR, "Flushing encoder failed \ n"); goto end ;}}predict (ofmt_ctx); end: av_freep (avio_in); av_freep (avio_out ); av_free (inbuffer); av_free (outbuffer); av_free_packet (& packet); av_frame_free (& frame); convert (& ifmt_ctx); avformat_free_context (ofmt_ctx); fcloseall (); I F (ret <0) av_log (NULL, AV_LOG_ERROR, "Error occurred \ n"); return (ret? 1:0 );}
Result
Shows the program running result.
View the video information before Transcoding Using MediaInfo, as shown in.
Use MediaInfo to view the transcoded video information, as shown in.
Download
SourceForge project homepage:
Https://sourceforge.net/projects/simplestffmpegmemhandler/
CSDN project:
Http://download.csdn.net/detail/leixiaohua1020/8003731
Note:
This project contains two examples of FFmpeg read/write memory:
Simplest_ffmpeg_mem_player: Memory Player Based on FFmpeg.
Simplest_ffmpeg_mem_transcoder: Memory Transcoder Based on FFmpeg.
How to Use ffmpeg to decode data in memory
Live555 is not very familiar... However, the client should not parse the RTP packet first .. Then put it into the memory? If the stored video data is in H264 format, you can directly use ffmpeg to decode it .....
FFMPEG video Conversion Problems
Baidu Web Search: Video conversion master Professional Edition
Excellent domestic video format converter, professional conversion software, provides the ultimate solution for video format file conversion, it can read a variety of video and audio files, and quickly convert them to popular media file formats. Has a very beautiful and friendly interface. it covers almost all popular audio and video formats, including AVI, Mpg, RM, RMVB, 3GP, MP4, AMV, Mpeg, Mpeg1, Mpeg2, Mpeg4, VCD, SVCD, DVD, XVID, DivX, ASF, WMV, SWF, IPOD, PSP, GIF, MJPEG, QuickTime, MOV, FLV, MKV, DV, and all audio formats.
Supports FLV/F4V, AVI/DIVX/XVID/DIV, MPEG/MPG/DAT, WMV/ASF/ASX, RM/RMVB, MOV/QT, 3GP/3G2, MP4/M4V and all video formats that can be played. Batch file conversion is supported. How to convert mp4 to support secondary encoding to ensure optimal output video quality? You can directly convert any video file to 3GP/3G2 without losing the image quality, the output video supports multiple resolutions (QCIF, SQCIF, CIF, VGA, and QVGA ). Simple user interface, easy to use, and easy to set parameters