https://www.iteye.com/blog/lobin-2439912
C: Linux C 编程 - SDL+FFmpeg视频处理
播放mpg格式的视频
先准备一张mpg视频
./ffmpeg -y -i /cygdrive/h/IMG_0024-vcodec_copy-an.mp4 -f mpeg1video /cygdrive/h/IMG_0024-vcodec_copy-an-f-mpeg1video.mpg
这里指定-f mpeg1video表示是一种raw MPEG-1 video格式。
./ffprobe.exe /cygdrive/h/IMG_0024-vcodec_copy-an-f-mpeg1video.mpg ffprobe version 2.7.2 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.5.3 (GCC)
configuration: --enable-shared --prefix=/usr/local/ffmpeg
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
[mpegvideo @ 0x2001a200] Estimating duration from bitrate, this may be inaccurate
Input #0, mpegvideo, from '/cygdrive/h/IMG_0024-vcodec_copy-an-f-mpeg1video.mpg':
Duration: 00:00:00.80, bitrate: 104857 kb/s
Stream #0:0: Video: mpeg1video, yuv420p(tv), 320x568 [SAR 1:1 DAR 40:71], 104857 kb/s, 29.97 fps, 29.97 tbr, 1200k tbn, 29.97 tbc
>.\ffmpeg -y -i h:\av\IMG_0024.mp4 -f mpeg2video h:\av\IMG_0024-f-mpeg2video.mpg
>.\ffprobe.exe h:\av\IMG_0024-f-mpeg2video.mpg
ffprobe version 2.7.2 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.5.3 (GCC)
configuration: --enable-shared --prefix=/usr/local/ffmpeg
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
cygwin warning:
MS-DOS style path detected: h:\av\IMG_0024-f-mpeg2video.mpg
Preferred POSIX equivalent is: /cygdrive/h/av/IMG_0024-f-mpeg2video.
mpg
CYGWIN environment variable option "nodosfilewarning" turns off this
warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
Input #0, mpegvideo, from 'h:\av\IMG_0024-f-mpeg2video.mpg':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: mpeg2video (Main), yuv420p(tv), 320x568 [SAR 1
:1 DAR 40:71], max. 104857 kb/s, 29.97 fps, 29.97 tbr, 1200k tbn, 59.9
4 tbc
上面在将一张mp4视频文件转换为mpg视频文件时指定的是-f mpeg1video,如果采用下面的方式转换的话,在程序中解码会出错。
>.\ffmpeg -y -i h:\av\IMG_0024.mp4 -c:v mpeg1video h:\av\IMG_0024-c-v-mpeg1video.mpg
>.\ffprobe.exe h:\av\IMG_0024-c-v-mpeg1video.mpg
ffprobe version 2.7.2 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.5.3 (GCC)
configuration: --enable-shared --prefix=/usr/local/ffmpeg
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
cygwin warning:
MS-DOS style path detected: h:\av\IMG_0024-c-v-mpeg1video.mpg
Preferred POSIX equivalent is: /cygdrive/h/av/IMG_0024-c-v-mpeg1vide
o.mpg
CYGWIN environment variable option "nodosfilewarning" turns off this
warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
Input #0, mpeg, from 'h:\av\IMG_0024-c-v-mpeg1video.mpg':
Duration: 00:03:00.09, start: 0.522456, bitrate: 856 kb/s
Stream #0:0[0x1e0]: Video: mpeg1video, yuv420p(tv), 320x568 [SAR 1
:1 DAR 40:71], 104857 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 29.97 tbc
Stream #0:1[0x1c0]: Audio: mp2, 44100 Hz, stereo, s16p, 384 kb/s
./ffmpeg -i /cygdrive/h/IMG_0024-vcodec_copy-an.mp4 -c:v mpeg1video /cygdrive/h/IMG_0024-vcodec_copy-an-c-v-mpeg1video.mpg
这里指定-c:v mpeg1video表示MPEG-1 video格式。
>.\ffmpeg -y -i h:\av\IMG_0024.mp4 -c:v mpeg2video h:\av\IMG_0024-c-v-mpeg2video.mpg
>.\ffprobe.exe h:\av\IMG_0024-c-v-mpeg2video.mpg
ffprobe version 2.7.2 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.5.3 (GCC)
configuration: --enable-shared --prefix=/usr/local/ffmpeg
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
cygwin warning:
MS-DOS style path detected: h:\av\IMG_0024-c-v-mpeg2video.mpg
Preferred POSIX equivalent is: /cygdrive/h/av/IMG_0024-c-v-mpeg2vide
o.mpg
CYGWIN environment variable option "nodosfilewarning" turns off this
warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
Input #0, mpeg, from 'h:\av\IMG_0024-c-v-mpeg2video.mpg':
Duration: 00:03:00.11, start: 0.522456, bitrate: 904 kb/s
Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 320x568
[SAR 1:1 DAR 40:71], max. 104857 kb/s, 29.97 fps, 29.97 tbr, 90k tbn,
59.94 tbc
Stream #0:1[0x1c0]: Audio: mp2, 44100 Hz, stereo, s16p, 384 kb/s
这两种转换方式结果都差不多:
./ffprobe.exe /cygdrive/h/IMG_0024-vcodec_copy-an-f-mpeg1video.mpg
ffprobe version 2.7.2 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.5.3 (GCC)
configuration: --enable-shared --prefix=/usr/local/ffmpeg
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
[mpegvideo @ 0x2001a200] Estimating duration from bitrate, this may be inaccurate
Input #0, mpegvideo, from '/cygdrive/h/IMG_0024-vcodec_copy-an-f-mpeg1video.mpg':
Duration: 00:00:00.80, bitrate: 104857 kb/s
Stream #0:0: Video: mpeg1video, yuv420p(tv), 320x568 [SAR 1:1 DAR 40:71], 104857 kb/s, 29.97 fps, 29.97 tbr, 1200k tbn, 29.97 tbc
./ffprobe.exe /cygdrive/h/IMG_0024-vcodec_copy-an-c-v-mpeg1video.mpg
ffprobe version 2.7.2 Copyright (c) 2007-2015 the FFmpeg developers
built with gcc 4.5.3 (GCC)
configuration: --enable-shared --prefix=/usr/local/ffmpeg
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
Input #0, mpeg, from '/cygdrive/h/IMG_0024-vcodec_copy-an-c-v-mpeg1video.mpg':
Duration: 00:03:00.05, start: 0.533367, bitrate: 469 kb/s
Stream #0:0[0x1e0]: Video: mpeg1video, yuv420p(tv), 320x568 [SAR 1:1 DAR 40:71], 104857 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 29.97 tbc
除了一些参数不太一样,里边区别比较大的是:
1、Duration
第1种方式显示才00:00:00.80毫秒,第2中显示00:03:00.05比较正常。
2、Input #0
第1种方式后面是mpegvideo,第2中后面是mpeg。
#include<stdio.h> #include<string.h> #include<SDL_video.h> #include<SDL_render.h> #include<SDL_surface.h> #include<SDL_events.h> #include<libavformat/avformat.h> #include<libavcodec/avcodec.h> #define INBUF_SIZE 4096 int read_video(FILE *fp, SDL_Renderer *renderer, SDL_Texture *texture, int center, int full_screen, int width, int height) { SDL_Rect rect; AVPacket av_packet; AVCodec *av_codec; AVCodecContext *av_codec_context; AVFrame *av_frame; int frame_count; uint8_t inbuf[INBUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; unsigned char *buf; int buf_size; memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE); avcodec_register_all(); av_init_packet(&av_packet); av_codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO); if (av_codec == NULL) { fprintf(stderr, "Decoder ont found\n"); return 1; } av_codec_context = avcodec_alloc_context3(av_codec); if (av_codec_context == NULL) { fprintf(stderr, "Cann't alloc video codec context\n"); return 1; } if(av_codec->capabilities & CODEC_CAP_TRUNCATED) { av_codec_context->flags |= CODEC_FLAG_TRUNCATED; } if (avcodec_open2(av_codec_context, av_codec, NULL)) { fprintf(stderr, "Cann't open codec\n"); return 1; } av_frame = av_frame_alloc(); if (av_frame == NULL) { fprintf(stderr, "Cann't allocate video frame\n"); return 1; } frame_count = 0; while (1) { av_packet.size = fread(inbuf, 1, INBUF_SIZE, fp); if (av_packet.size == 0) { break; } //fprintf(stdout, "%d bytes readed...\n", av_packet.size); av_packet.data = inbuf; while(av_packet.size > 0) { int nbytes; int got; nbytes = avcodec_decode_video2(av_codec_context, av_frame, &got, &av_packet); if (nbytes < 0) { fprintf(stderr, "Fail to decoding frame--- %d\n", frame_count); return 1; } if (got) { int i; buf_size = av_codec_context->width * av_codec_context->height * 12 / 8;; buf = (unsigned char *) malloc(buf_size + 1); for (i = 0; i < av_codec_context->height; i++) { memcpy(buf + i * (av_frame->linesize[0]), av_frame->data[0] + i * av_frame->linesize[0], av_frame->linesize[0]); } for (i = 0; i < av_codec_context->height; i++) { memcpy(buf + av_codec_context->width * av_codec_context->height + i * (av_frame->linesize[1]) , av_frame->data[1] + i * av_frame->linesize[1], av_frame->linesize[1]); } //fprintf(stdout, "frame: line size 0: %d, line size 1: %d\n", av_frame->linesize[0], av_frame->linesize[1]); //fprintf(stdout, "codec context: width=%d, height=%d, frame: width=%d, height=%d\n", av_codec_context->width, av_codec_context->height, av_frame->width, av_frame->height); SDL_UpdateTexture(texture, NULL, buf, av_codec_context->width); rect.x = center ? (width - av_codec_context->width) / 2 : 0; rect.y = center ? (height - av_codec_context->height) / 2 : 0; rect.w = full_screen ? width : av_codec_context->width; rect.h = full_screen ? height : av_codec_context->height; SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, &rect); SDL_RenderPresent(renderer); SDL_Delay(40); frame_count++; } if (av_packet.data) { av_packet.size -= nbytes; av_packet.data += nbytes; } } } //* av_packet.data = NULL; av_packet.size = 0; { int nbytes; int got; nbytes = avcodec_decode_video2(av_codec_context, av_frame, &got, &av_packet); if (nbytes < 0) { fprintf(stderr, "Fail to decoding frame %d\n", frame_count); return 1; } if (got) { int i; buf_size = av_codec_context->width * av_codec_context->height * 12 / 8;; buf = (unsigned char *) malloc(buf_size + 1); for (i = 0; i < av_codec_context->height; i++) { memcpy(buf + i * (av_frame->linesize[0]), av_frame->data[0] + i * av_frame->linesize[0], av_frame->linesize[0]); } for (i = 0; i < av_codec_context->height; i++) { memcpy(buf + av_codec_context->width * av_codec_context->height + i * (av_frame->linesize[1]) , av_frame->data[1] + i * av_frame->linesize[1], av_frame->linesize[1]); } SDL_UpdateTexture(texture, NULL, buf, av_codec_context->width); rect.x = center ? (width - av_codec_context->width) / 2 : 0; rect.y = center ? (height - av_codec_context->height) / 2 : 0; rect.w = full_screen ? width : av_codec_context->width; rect.h = full_screen ? height : av_codec_context->height; SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, &rect); SDL_RenderPresent(renderer); SDL_Delay(40); frame_count++; } if (av_packet.data) { av_packet.size -= nbytes; av_packet.data += nbytes; } } //*/ fclose(fp); av_free(av_codec_context); av_frame_free(&av_frame); return 0; } int main(int argc, char** argv) { char* filename; FILE *fp = NULL; AVFormatContext *av_format_context = NULL; AVInputFormat *av_input_format = NULL; AVDictionary **av_dictionary = NULL; SDL_Window *pWin; int width = 640; int height = 360; SDL_Renderer *renderer; SDL_Texture *texture; int pix_width = 0; int pix_height = 0; // sample bit size int sample_bit_size = 12;// 24 * 8; // 12; 1; int center = 0; int full_screen = 0; SDL_Event e; int exit = 0; int i; filename = argv[1]; if (argc < 2) { fprintf(stderr, "invalid args.\n"); return 1; } filename = argv[1]; if (argc == 3) { char* param = argv[2]; if (strcmp(param, "--center") == 0) { center = !center; } } if (argc == 4) { char* param = argv[3]; if (strcmp(param, "--full-screen") == 0) { full_screen = !full_screen; } } av_register_all(); if (avformat_open_input(&av_format_context, filename, av_input_format, av_dictionary)) { fprintf(stderr, "open input err: %s\n", filename); return 1; } if (av_format_context == NULL) { fprintf(stderr, "open input err: %s, format=null\n", filename); return 1; } if (avformat_find_stream_info(av_format_context, av_dictionary) < 0) { fprintf(stderr, "find stream info err\n"); return 1; } for (i = 0; i < av_format_context->nb_streams; i++) { AVStream *st = av_format_context->streams[i]; AVCodecContext *av_codec_context = st->codec; switch (av_codec_context->codec_type) { case AVMEDIA_TYPE_VIDEO: pix_width = av_codec_context->width; pix_height = av_codec_context->height; break; } } if (pix_width <= 0 || pix_height <= 0) { fprintf(stderr, "invalid arg: pix width or height.\n"); return 1; } if (pix_width > width) { width = pix_width; } if (pix_height > height) { height = pix_height; } fprintf(stdout, "video: %s, pixel: width=%d, height=%d, window: width=%d, height=%d, full screen:%s.\n", filename, pix_width, pix_height, width, height, full_screen ? "yes" : "no"); pWin = SDL_CreateWindow("Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_MAXIMIZED); // SDL_WINDOW_FULLSCREEN, SDL_WINDOW_RESIZABLE if (pWin == NULL) { fprintf(stderr, "create window err.\n"); return 1; } SDL_GetWindowSize(pWin, &width, &height); fprintf(stdout, "video: %s, pixel: width=%d, height=%d, window: width=%d, height=%d, full screen:%s.\n", filename, pix_width, pix_height, width, height, full_screen ? "yes" : "no"); renderer = SDL_CreateRenderer(pWin, -1, 0); if (renderer == NULL) { fprintf(stderr, "create renderer err: %s\n", SDL_GetError()); return 1; } texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, pix_width, pix_height); //texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YUY2, SDL_TEXTUREACCESS_STREAMING, pix_width, pix_height); //texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_UYVY, SDL_TEXTUREACCESS_STREAMING, pix_width, pix_height); //texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YVYU, SDL_TEXTUREACCESS_STREAMING, pix_width, pix_height); if (texture == NULL) { fprintf(stderr, "create texture err: %s\n", SDL_GetError()); return 1; } fp = fopen(filename, "rb"); if (fp == NULL) { fprintf(stderr, "open err: %s\n", filename); return 1; } read_video(fp, renderer, texture, center, full_screen, width, height); while (! exit) { while (SDL_PollEvent(&e)) { if (e.type == SDL_QUIT) { exit = 1; } } } SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(pWin); SDL_Quit(); return 0; }
编译链接
编译的时候注意通过“-I”指定头文件目录,在链接的时候通过“-L”指定要链接的静态库文件目录,以及通过“-l”指定要链接的静态库。
gcc -I D:\sbin\usr\local\sdl\include\SDL2 -I D:\sbin\usr\local\ffmpeg\include -L D:\sbin\usr\local\sdl\lib -L D:\sbin\usr\local\ffmpeg\lib sdl_ffmpeg_video_test.c -o sdl_ffmpeg_video_test -lSDL2 -lavformat -lavcodec -lavutil
.\sdl_ffmpeg_video_test h:\\IMG_0024-vcodec_copy-an-f-mpeg1video.mpg
.\sdl_ffmpeg_video_test h:\\IMG_0024-vcodec_copy-an-f-mpeg1video.mpg --center
.\sdl_ffmpeg_video_test h:\\IMG_0024-vcodec_copy-an-f-mpeg1video.mpg --center --full-screen
相关推荐
FFmpeg 是一个强大的开源多媒体处理工具,用于处理音频和视频文件。这个压缩包"ffmpeg-master-latest-win64-gpl-shared"是针对Windows 64位操作系统编译的最新FFmpeg版本,包含了动态链接库(shared),这意味着在...
FFmpeg是一款强大的开源多媒体处理工具,它在Linux环境下被广泛用于音视频的编码、转换、流传输以及录制等任务。本资源"Linux下使用FFmpeg录屏代码.rar"包含了一个利用FFmpeg在Linux系统上进行屏幕录制的示例项目。...
在Linux中,使用ALSA库的pcm(脉冲编码调制)子系统,可以通过`arecord`命令行工具或者编程接口(例如`snd_pcm_open()`函数)来打开和操作音频设备,获取麦克风的实时音频数据。 3. **FFmpeg:多媒体处理框架** ...
1. **FFmpeg概述**:FFmpeg是一个跨平台的项目,支持Linux、Windows、Mac OS X等多种操作系统。它的主要功能包括音视频的编码、解码、转码、格式转换、流媒体处理和抓取等。 2. **libavcodec**:这是FFmpeg的核心...
FFmpeg是一个开源的多媒体处理框架,能够处理音频、视频和图像。在OpenCV中,FFmpeg用于读取、解码、编码和流化多媒体数据。`opencv-ffmpeg.dll` 和 `opencv-ffmpeg-6` 文件可能是OpenCV针对FFmpeg的特定版本的动态...
4. **Linux编程**:在Linux环境下编译和运行项目,使用makefile或CMakeLists.txt进行项目配置,以及熟悉shell脚本等。 5. **跨平台开发**:了解如何使代码在不同操作系统上运行,包括处理路径、文件系统差异和库的...
FFMpeg 在 Linux 下的编译和使用 FFMpeg 是一个功能强大且广泛使用的开源多媒体处理框架,它可以对多种格式的音频和视频文件进行处理,包括编码、解码、转换、流媒体等。今天,我们将介绍如何在 Linux 操作系统下...
4. **多平台兼容性**:FFmpeg是跨平台的,可以在Windows、Linux、macOS等多种操作系统上运行,这使得开发者可以编写一次代码,部署到多个平台。 5. **API使用**:开发者需要熟悉FFmpeg的API,例如avcodec、avformat...
它支持多种编程语言,如C++、Python、Java等,具有跨平台性,可在Windows、Linux、Mac OS、Android和iOS等系统上运行。 FFmpeg则是一个全面的多媒体框架,包含了一系列用于音视频处理的工具和库。它可以用于音视频...
在本项目"Linux开发板项目-多媒体娱乐盒"中,我们关注的是利用Linux系统构建一个功能丰富的多媒体娱乐设备。...项目的具体实现会涉及到大量的编程和调试工作,以及对Linux系统、多媒体处理和硬件特性的深入理解。
- **编写API接口**:封装FFmpeg和FDK-AAC的C语言接口,使其适应Objective-C或Swift编程模型。 - **实现功能**:根据需求,实现音频的读取、编码、解码、写入等功能。 4. **应用场景:** - **实时通信**:在语音...
**nim-ffmpeg** 是一个将 **ffmpeg** 库与 **Nim** 编程语言结合的项目,使得Nim程序员可以方便地利用ffmpeg的强大功能进行音视频处理。Nim是一种现代、系统级、表达力强的编程语言,设计目标是高效、灵活且易于学习...
4. **API 使用**:FFmpeg 提供了一套C语言的API,开发者可以通过这些API来实现自己的多媒体应用。例如,可以使用 libavformat API 打开和读取多媒体文件,libavcodec API 进行编码和解码操作,libavfilter API 实现...
FFmpeg和OpenCV是两个强大的开源工具,它们在多媒体处理领域有着广泛的应用。FFmpeg是一个全面的、跨平台的解决方案,用于处理音频和视频文件,包括录制、转换、流式传输等功能。OpenCV则主要用于计算机视觉,但它也...
FFmpeg 是一个强大的开源多媒体处理工具,用于处理音频、视频以及图像文件。它是一个跨平台的解决方案,可以在多个操作系统上运行,包括 Linux、Windows 和 macOS。在这个特定的场景中,我们关注的是 "ffmpeg-3.1.2-...
在C++编程环境中,利用FFmpeg库可以实现屏幕录制功能,而`x11grab`是FFmpeg中用于从X11窗口系统抓取视频流的模块,特别适用于在Linux环境下录制桌面操作。 首先,你需要确保已经正确地在你的系统上安装了FFmpeg库,...
FFmpeg 是一个强大的开源多媒体处理工具,用于处理音频和视频文件。这个名为 "ffmpeg-0.10.3" 的版本是 FFmpeg 的一个较早的稳定版本,它包含了多种功能,可以进行视频编码、解码、转换、流处理以及各种多媒体格式的...
总的来说,"android-ffmpeg-player"项目展示了如何在Android上利用ffmpeg构建一个自定义的视频播放器,涉及到的技能包括Android NDK编程、ffmpeg库的使用、JNI接口设计以及多媒体播放的原理。这个项目对于希望深入...
首先,你需要具备C语言编程基础,因为FFmpeg主要由C语言编写。同时,了解基本的编译构建系统如autotools或CMake也是必要的,因为这将决定如何配置和编译源码。 1. **源码结构**:FFmpeg源码通常按照模块划分,包括...
FFmpeg是一款强大的开源多媒体处理工具,它包含了众多的编解码器、音视频过滤器以及各种多媒体相关的功能。这个“ffmpeg-4.3.1-win64-shared.zip”压缩包提供的是FFmpeg的一个预编译的Windows 64位共享版本,意味着...