The simplest example of memory read/write based on FFMPEG: Memory player

Source: Internet
Author: User
Tags file url fread

We plan to record two examples of the simplest FFMPEG for memory read/write. All previous FFMPEG examples operate on files. For example, "100-line code implementation of the simplest Video Player Based on FFMPEG + SDL" plays a video file. The simplest FFMPEG-based transcoding program also converts a video file into another video file. The simplest Video Encoder Based on FFMPEG (YUV encoding is H.264) is also the final encoding to get an H.264 video file. In fact, not all videos are encoded and decoded for files. Sometimes the decoded video data is stored in a memory. For example, video data sent from other systems. Similarly, sometimes the encoded video data does not need to be saved as a file. For example, you must send the encoded video data to another system for further processing. In the above two cases, FFmpeg is required not only to perform the "read, write" Operation on the file, but to perform the "read, write" Operation on the memory. Two examples to be recorded are examples of using FFMPEG to read and write memory.

Examples of FFMPEG read/write memory have been described in the article "FFMPEG reads data from memory (or outputs data to memory)", but there has been no complete code project. This document describes the simplest FFMPEG-based memory player. In this example, the video data in the file is first read to the memory through fread (), and then the data in the memory is played using FFMPEG.

The second example recorded in the next article is "the simplest FFMPEG-based memory Transcoder". In this example, the video data in the file is first read to the memory through fread (), and then the data is read and transcoded using FFMPEG, output The transcoded data to another memory, and write the data into a file through fwrite.

For details about how to read data from memory, refer to the article:

FFmpeg reads data from memory (or outputs data to memory)

Key Points

There are two key points:

1. initialize the custom aviocontext and specify the custom callback function. The sample code is as follows:


// Cache in AVIOContext
unsigned char * aviobuffer = (unsigned char *) av_malloc (32768);
AVIOContext * avio = avio_alloc_context (aviobuffer, 32768,0, NULL, read_buffer, NULL, NULL);
pFormatCtx-> pb = avio;
 
if (avformat_open_input (& pFormatCtx, NULL, NULL, NULL)! = 0) {
            printf ("Could n‘t open inputstream. \ n");
            return -1;
}


In the above Code, the callback function read_buffer () is customized (). When you use avformat_open_input () to open media data, you can choose not to specify the File URL, that is, the 2nd parameter is null (because the data is not read by the file, but by read_buffer () provided)

2. Write the callback function by yourself. The sample code is as follows:



//Callback
int read_buffer(void *opaque, uint8_t *buf, int buf_size){
	if(!feof(fp_open)){
		inttrue_size=fread(buf,1,buf_size,fp_open);
		return true_size;
	}else{
		return -1;
	}
}


When the system needs data, the callback function is automatically called to obtain data. In this example, fread () is directly used to read data to the memory for simplicity. The callback function must pay special attention to its parameters and return values.

 

Source code

The source code of the program is directly pasted below:

 

/ **
 * The simplest example of memory reading and writing based on FFmpeg (memory player)
 * Simplest FFmpeg mem Player
 *
 * Lei Xiaoyu
 * [email protected]
 * Communication University of China / Digital TV Technology
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 * This program implements playback of video data in memory.
 * Is the simplest example of using FFmpeg to read memory.
 *
 * This software play video data in memory (not a file).
 * It ’s the simplest example to use FFmpeg to read from memory.
 *
 * /


#include <stdio.h>

extern "C"
{
#include "libavcodec / avcodec.h"
#include "libavformat / avformat.h"
#include "libswscale / swscale.h"
// SDL
#include "sdl / SDL.h"
#include "sdl / SDL_thread.h"
};

// Output YUV420P
#define OUTPUT_YUV420P 0
FILE * fp_open = NULL;

// Callback
int 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;
}

}


int main (int argc, char * argv [])
{

AVFormatContext * pFormatCtx;
int i, videoindex;
AVCodecContext * pCodecCtx;
AVCodec * pCodec;
char filepath [] = "cuc60anniversary_start.mkv";
Ranch
av_register_all ();
avformat_network_init ();
pFormatCtx = avformat_alloc_context ();
Ranch
fp_open = fopen (filepath, "rb +");
// Cache in AVIOContext
unsigned char * aviobuffer = (unsigned char *) av_malloc (32768);
AVIOContext * avio = avio_alloc_context (aviobuffer, 32768,0, NULL, read_buffer, NULL, NULL);
pFormatCtx-> pb = avio;

if (avformat_open_input (& pFormatCtx, NULL, NULL, NULL)! = 0) {
printf ("Could n‘t open input stream. \ n");
return -1;
}
if (av_find_stream_info (pFormatCtx) <0) {
printf ("Could n‘t find stream information. \ n");
return -1;
}
videoindex = -1;
for (i = 0; i <pFormatCtx-> nb_streams; i ++)
if (pFormatCtx-> streams [i]-> codec-> codec_type == AVMEDIA_TYPE_VIDEO) {
videoindex = i;
break;
}
if (videoindex ==-1) {
printf ("Did n‘t find a video stream. \ n");
return -1;
}
pCodecCtx = pFormatCtx-> streams [videoindex]-> codec;
pCodec = avcodec_find_decoder (pCodecCtx-> codec_id);
if (pCodec == NULL) {
printf ("Codec not found. \ n");
return -1;
}
if (avcodec_open2 (pCodecCtx, pCodec, NULL) <0) {
printf ("Could not open codec. \ n");
return -1;
}
AVFrame * pFrame, * pFrameYUV;
pFrame = avcodec_alloc_frame ();
pFrameYUV = avcodec_alloc_frame ();
uint8_t * out_buffer = (uint8_t *) av_malloc (avpicture_get_size (PIX_FMT_YUV420P, pCodecCtx-> width, pCodecCtx-> height));
avpicture_fill ((AVPicture *) pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx-> width, pCodecCtx-> height);
// SDL ----------------------------
if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
printf ("Could not initialize SDL-% s \ n", SDL_GetError ());
return -1;
}

int screen_w = 0, screen_h = 0;
SDL_Surface * screen;
screen_w = pCodecCtx-> width;
screen_h = pCodecCtx-> height;
screen = SDL_SetVideoMode (screen_w, screen_h, 0,0);

if (! screen) {
printf ("SDL: could not set video mode-exiting:% s \ n", SDL_GetError ());
return -1;
}
SDL_Overlay * bmp;
bmp = SDL_CreateYUVOverlay (pCodecCtx-> width, pCodecCtx-> height, SDL_YV12_OVERLAY, screen);
SDL_Rect rect;
// SDL End ------------------------
int ret, got_picture;

AVPacket * packet = (AVPacket *) av_malloc (sizeof (AVPacket));
// Output Information -----------------------------
printf ("File Information --------------------------------- \ n");
av_dump_format (pFormatCtx, 0, filepath, 0);
printf ("----------------------------------------------- -\ n ");

#if OUTPUT_YUV420P
    FILE * fp_yuv = fopen ("output.yuv", "wb +");
#endif

struct SwsContext * img_convert_ctx;
img_convert_ctx = sws_getContext (pCodecCtx-> width, pCodecCtx-> height, pCodecCtx-> pix_fmt, pCodecCtx-> width, pCodecCtx-> height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL)
// ------------------------------
while (av_read_frame (pFormatCtx, packet)> = 0) {
if (packet-> stream_index == videoindex) {
ret = avcodec_decode_video2 (pCodecCtx, pFrame, & got_picture, packet);
if (ret <0) {
printf ("Decode Error. \ n");
return -1;
}
if (got_picture) {
sws_scale (img_convert_ctx, (const uint8_t * const *) pFrame-> data, pFrame-> linesize, 0, pCodecCtx-> height, pFrameYUV-> data, pFrameYUV-> linesize);
#if OUTPUT_YUV420P
int y_size = pCodecCtx-> width * pCodecCtx-> height;
fwrite (pFrameYUV-> data [0], 1, y_size, fp_yuv); // Y
fwrite (pFrameYUV-> data [1], 1, y_size / 4, fp_yuv); // U
fwrite (pFrameYUV-> data [2], 1, y_size / 4, fp_yuv); // V
#endif
SDL_LockYUVOverlay (bmp);
bmp-> pixels [0] = pFrameYUV-> data [0];
bmp-> pixels [2] = pFrameYUV-> data [1];
bmp-> pixels [1] = pFrameYUV-> data [2];
bmp-> pitches [0] = pFrameYUV-> linesize [0];
bmp-> pitches [2] = pFrameYUV-> linesize [1];
bmp-> pitches [1] = pFrameYUV-> linesize [2];
SDL_UnlockYUVOverlay (bmp);
rect.x = 0;
rect.y = 0;
rect.w = screen_w;
rect.h = screen_h;
SDL_DisplayYUVOverlay (bmp, & rect);
// Delay 40ms
SDL_Delay (40);
}
}
av_free_packet (packet);
}
sws_freeContext (img_convert_ctx);

#if OUTPUT_YUV420P
    fclose (fp_yuv);
#endif

fclose (fp_open);

SDL_Quit ();

av_free (out_buffer);
av_free (pFrameY
UV);
avcodec_close (pCodecCtx);
avformat_close_input (& pFormatCtx);

return 0;
} 


 

You can determine whether to output the decoded yuv420p data into a file through the macro defined in the Code:


#define OUTPUT_YUV420P 0 


Result

The running result of the program is as follows. You can decode and play the test video. The celebration of the 60th anniversary was followed by a short opening scene of the gala as a test video for the alma mater ~


 

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 (record in the next article ).


The simplest example of memory read/write based on FFMPEG: Memory player

Alibaba Cloud Hot Products

Elastic Compute Service (ECS) Dedicated Host (DDH) ApsaraDB RDS for MySQL (RDS) ApsaraDB for PolarDB(PolarDB) AnalyticDB for PostgreSQL (ADB for PG)
AnalyticDB for MySQL(ADB for MySQL) Data Transmission Service (DTS) Server Load Balancer (SLB) Global Accelerator (GA) Cloud Enterprise Network (CEN)
Object Storage Service (OSS) Content Delivery Network (CDN) Short Message Service (SMS) Container Service for Kubernetes (ACK) Data Lake Analytics (DLA)

ApsaraDB for Redis (Redis)

ApsaraDB for MongoDB (MongoDB) NAT Gateway VPN Gateway Cloud Firewall
Anti-DDoS Web Application Firewall (WAF) Log Service DataWorks MaxCompute
Elastic MapReduce (EMR) Elasticsearch

Alibaba Cloud Free Trail

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.