學習改造源碼

0 背景介紹html

 

 

 

 

 

 

 

FFmpeg is a name of a free software project for the multimedia handling licensed under GNU General Public License. 
The most popular part of the project is ffmpeg command line tool for video and audio encoding/decoding and its main features are the high speed, 
quality of output and small file sizes. "FF" from FFmpeg means Fast Forward - a control button on media players, 
and "mpeg" is an abbreviation of the Moving Pictures Experts Group. The FFmpeg logo contains a zig-zag pattern, 
that is characteristic for the entropy coding scheme illustrated with 8x8 block in the picture.

 

調用ffmpeg能夠很是容易合併左右聲道的音頻爲立體聲好比java

ffmpeg -i 1.wav -i 2.wav -filter_complex "amovie=1.wav [l]; amovie=2.wav [r]; [l] [r] amerge"  1_2.mp3

具體細節請參考博文http://www.cnblogs.com/hdu-2010/p/5791097.html。可是每次調用命令都會頻繁切換進程,涉及OS的調度。在數據量很大,且實時性要求很高的時候,不免會浪費沒必要要的時間。因此下面介紹怎麼改造ffmpeg的源碼,使得ffmpeg常住內存,並轉換咱們的待合併文件。linux

 

 

1 ffmpeg源碼windows

ffmpeg-3.1.2的源碼解壓後的目錄結構如圖所示服務器

 

 ffmpeg.c中main函數以下,當輸入命令行的時候,下面的main函數開始執行諸如,初始化,參數解析,合併轉換,內存釋放等步驟。本文的重點就是改造下面的main函數。ide

 

 1 int main(int argc, char **argv)  //main  
 2 {
 3     int ret;
 4     int64_t ti;
 5 
 6     init_dynload();
 7 
 8     register_exit(ffmpeg_cleanup);
 9 
10     setvbuf(stderr,NULL,_IONBF,0); /* win32 runtime needs this */
11 
12     av_log_set_flags(AV_LOG_SKIP_REPEATED);
13     parse_loglevel(argc, argv, options);
14 
15     if(argc>1 && !strcmp(argv[1], "-d")){
16         run_as_daemon=1;
17         av_log_set_callback(log_callback_null);
18         argc--;
19         argv++;
20     }
21 
22     avcodec_register_all();
23 #if CONFIG_AVDEVICE
24     avdevice_register_all();
25 #endif
26     avfilter_register_all();
27     av_register_all();
28     avformat_network_init();
29 
30     show_banner(argc, argv, options);
31 
32     term_init();
33 
34     /* parse options and open all input/output files */
35     ret = ffmpeg_parse_options(argc, argv);
36     if (ret < 0)
37         exit_program(1);
38 
39     if (nb_output_files <= 0 && nb_input_files == 0) {
40         show_usage();
41         av_log(NULL, AV_LOG_WARNING, "Use -h to get full help or, even better, run 'man %s'\n", program_name);
42         exit_program(1);
43     }
44 
45     /* file converter / grab */
46     if (nb_output_files <= 0) {
47         av_log(NULL, AV_LOG_FATAL, "At least one output file must be specified\n");
48         exit_program(1);
49     }
50 
51 //     if (nb_input_files == 0) {
52 //         av_log(NULL, AV_LOG_FATAL, "At least one input file must be specified\n");
53 //         exit_program(1);
54 //     }
55 
56     current_time = ti = getutime();
57     if (transcode() < 0)
58         exit_program(1);
59     ti = getutime() - ti;
60     if (do_benchmark) {
61         av_log(NULL, AV_LOG_INFO, "bench: utime=%0.3fs\n", ti / 1000000.0);
62     }
63     av_log(NULL, AV_LOG_DEBUG, "%"PRIu64" frames successfully decoded, %"PRIu64" decoding errors\n",
64            decode_error_stat[0], decode_error_stat[1]);
65     if ((decode_error_stat[0] + decode_error_stat[1]) * max_error_rate < decode_error_stat[1])
66         exit_program(69);
67 
68     exit_program(received_nb_signals ? 255 : main_return_code);
69     return main_return_code;
70 }
ffmpeg_main

 

2 編譯函數

爲了快速調試代碼,須要有以下幾點的準備工做。下面的工做是在LINUX Red Hat Enterprise Linux Server release 5.4 (Tikanga) 版本中測試的。學習

1 在Linux上安裝ffmpeg,具體安裝步驟可參看篇首提供的博文。
2 在安裝ffmpeg源碼包中,複製在執行./configure時生成的config.h文件,還有(cmdutils.h ,ffmpeg.h) 2個。
3 複製在編譯階段生成的.o 文件。主要是(ffmpeg_opt.o cmdutils.o ffmpeg_filter.o)3個。
4 新建工程目錄new_ffmpeg, 把上述複製的文件放入其中,外加ffmpeg.c。此時,一共有7個文件,可是在編譯以前須要對ffmpeg.c作些改變,不然編譯通不過。
5 編譯
6 連接
7 測試

 若是須要在windows下面測試,可參考已故音頻專家雷霄驊的博客,裏面有許多有價值的可debug的工程文件。測試

 

 3 測試this

爲了常駐內存

1 就須要對main函數中的exit_program函數改造,該函數 在register_exit(ffmpeg_cleanup)步驟, 這裏是調用了ffmpeg_cleanup函數。刪除exit_program,用ffmpeg_cleanup函數代替。

2 改造ffmpeg.c中的全局變量,防止轉換出錯。

 

 4 靜態編譯和動態編譯

 1 //hello.h
 2 
 3 #ifndef __TEST_LIB__
 4 #define __TEST_LIB__
 5 
 6 void hello(const char *name);
 7 #endif
 8 
 9 //hello.c
10 
11 #include <stdio.h>
12 
13 void hello(const char *name)
14 {
15     printf("hello %s\n", name);
16 }
17 
18 //main.c
19 
20 #include "hello.h"
21 
22 int main()
23 {
24     hello("everyone");
25     return 0;
26 }

 

4.1 靜態編譯

0 原始文件 hello.c hello.h main.c
1
$ gcc -c hello.c #生成.o文件 2 $ ar cr libmyhello.a hello.o #生成靜態文件libmyhello.a,注意庫文件的命名方式 3 $ gcc -o hello main.c -L. -lmyhello #鏈接庫文件,生成可執行的靜態文件 hello 4 $ ./hello #測試 hello everyone

4.2 動態編譯

0 原始文件  hello.c  hello.h  main.c
1 $gcc -c -fPIC hello.c  #生成共享的.o文件
2 $gcc -shared -fPIC -o libmyhello.so hello.o #生成動態庫libmyhello.so
3 $gcc -o hello main.c -L. -lmyhello #連接動態庫
4 $./hello  #測試

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: No such file or directory

只需把當前目錄動態庫libmyhello.so放入 /usr/local/lib下便可。
或者在第3步指定連接器的路徑,即
3 $gcc -o hello main.c -L. -lmyhello -Wl,-rpath=. #指定連接目錄
4 $./hello #測試
hello everyone

 

 

 

 

 

 

參考資料

 

1 ffmpeg下載  http://ffmpeg.org/releases/ffmpeg-3.1.2.tar.bz2

2 雷霄驊(leixiaohua1020)的專欄 ffmpeg.c函數結構簡單分析(畫圖)  http://blog.csdn.net/leixiaohua1020/article/details/39760711 

3 [總結]FFMPEG視音頻編解碼零基礎學習方法  http://blog.csdn.net/leixiaohua1020/article/details/15811977/

4 linux動態編譯和靜態編譯 http://blog.csdn.net/l_yangliu/article/details/6951005

5 java amr格式轉mp3格式(完美解決Linux下轉換0K問題)

6 ffmpeg+ffserver多媒體服務器開發入門 http://blog.csdn.net/rootusers/article/details/49822499

相關文章
相關標籤/搜索