file_utils.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:11k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000-2002.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *  Bill May        wmay@cisco.com
  20.  *  Dave Mackie  dmackie@cisco.com
  21.  */
  22. #include "mp4live.h"
  23. #include "mp4live_gui.h"
  24. #include <mp4.h>
  25. #include <libmpeg3.h>
  26. GtkWidget* CreateFileCombo(char* entryText)
  27. {
  28. GList* list = NULL;
  29. list = g_list_append(list, entryText);
  30. for (int i = 0; i < NUM_FILE_HISTORY; i++) {
  31. char* fileName =
  32. MyConfig->GetStringValue(CONFIG_APP_FILE_0 + i);
  33. if (fileName == NULL || fileName[0] == ''
  34.   || !strcmp(fileName, entryText)) {
  35. continue;
  36. }
  37. list = g_list_append(list, fileName);
  38. }
  39. GtkWidget* combo = gtk_combo_new();
  40. gtk_combo_set_popdown_strings(GTK_COMBO(combo), list);
  41. gtk_combo_set_use_arrows_always(GTK_COMBO(combo), 1);
  42. GtkWidget* entry = GTK_COMBO(combo)->entry;
  43. gtk_entry_set_text(GTK_ENTRY(entry), entryText);
  44. return combo;
  45. }
  46. static GtkWidget* FileSelection;
  47. static GtkWidget* FileEntry;
  48. static GtkSignalFunc FileOkFunc;
  49. static void on_filename_selected(
  50. GtkFileSelection *widget, 
  51. gpointer data)
  52. {
  53. const gchar *name =
  54. gtk_file_selection_get_filename(GTK_FILE_SELECTION(FileSelection));
  55. gtk_entry_set_text(GTK_ENTRY(FileEntry), name);
  56. gtk_widget_show(FileEntry);
  57. gtk_grab_remove(FileSelection);
  58. gtk_widget_destroy(FileSelection);
  59. if (FileOkFunc) {
  60. (*FileOkFunc)();
  61. }
  62. }
  63. void FileBrowser(
  64. GtkWidget* fileEntry, 
  65. GtkSignalFunc okFunc)
  66. {
  67. FileEntry = fileEntry;
  68. FileOkFunc = okFunc;
  69. FileSelection = gtk_file_selection_new("Select File");
  70. gtk_file_selection_hide_fileop_buttons(
  71. GTK_FILE_SELECTION(FileSelection));
  72. gtk_signal_connect(
  73. GTK_OBJECT(GTK_FILE_SELECTION(FileSelection)->ok_button),
  74. "clicked",
  75. GTK_SIGNAL_FUNC(on_filename_selected),
  76. FileSelection);
  77. gtk_signal_connect_object(
  78. GTK_OBJECT(GTK_FILE_SELECTION(FileSelection)->cancel_button),
  79. "clicked",
  80. GTK_SIGNAL_FUNC(gtk_widget_destroy),
  81. GTK_OBJECT(FileSelection));
  82. gtk_widget_show(FileSelection);
  83. gtk_grab_add(FileSelection);
  84. }
  85. bool IsDevice(const char* fileName)
  86. {
  87. // LATER might also want to stat()
  88. return !strncmp(fileName, "/dev/", 5);
  89. }
  90. bool IsUrl(const char* name)
  91. {
  92. return (strchr(name, ':') != NULL);
  93. }
  94. bool IsMp4File(const char* fileName)
  95. {
  96. if (IsUrl(fileName)) {
  97. return false;
  98. }
  99. if (strlen(fileName) <= 4) {
  100. return false;
  101. return !strcmp(&fileName[strlen(fileName) - 4], ".mp4");
  102. }
  103. bool IsMpeg2File(const char* fileName)
  104. {
  105. if (IsUrl(fileName)) {
  106. return false;
  107. }
  108. if (strlen(fileName) <= 4) {
  109. return false;
  110. const char* ext3 = &fileName[strlen(fileName) - 4];
  111. return !strcmp(ext3, ".mpg")
  112. || !strcmp(ext3, ".vob");
  113. }
  114. int32_t Mp4FileDefaultAudio(char* fileName)
  115. {
  116. MP4FileHandle mp4File = MP4Read(fileName);
  117. if (mp4File == MP4_INVALID_FILE_HANDLE) {
  118. return -1;
  119. }
  120. MP4TrackId trackId = 
  121. MP4FindTrackId(mp4File, 0, MP4_AUDIO_TRACK_TYPE);
  122. MP4Close(mp4File);
  123. if (trackId == MP4_INVALID_TRACK_ID) {
  124. return -1;
  125. }
  126. return trackId;
  127. }
  128. int32_t Mpeg2FileDefaultAudio(char* fileName)
  129. {
  130. mpeg3_t* mpeg2File = mpeg3_open(fileName);
  131. if (!mpeg2File) {
  132. return -1;
  133. }
  134. int32_t audioTracks = mpeg3_total_astreams(mpeg2File);
  135. mpeg3_close(mpeg2File);
  136. if (audioTracks <= 0) {
  137. return -1;
  138. }
  139. return 0; 
  140. }
  141. int32_t FileDefaultAudio(char* fileName)
  142. {
  143. if (IsMp4File(fileName)) {
  144. return Mp4FileDefaultAudio(fileName);
  145. } else if (IsMpeg2File(fileName)) {
  146. return Mpeg2FileDefaultAudio(fileName);
  147. } else {
  148. return 0;
  149. }
  150. }
  151. static char** trackNames;
  152. static u_int32_t* pTrackIndex;
  153. static void on_track_menu_activate(GtkWidget *widget, gpointer data)
  154. {
  155. *pTrackIndex = ((unsigned int)data) & 0xFF;
  156. }
  157. static GtkWidget* CreateNullTrackMenu(
  158. GtkWidget* menu,
  159. char type,
  160. char* source,
  161. u_int32_t* pIndex,
  162. u_int32_t* pNumber,
  163. u_int32_t** ppValues)
  164. {
  165. u_int32_t* newTrackValues = 
  166. (u_int32_t*)malloc(sizeof(u_int32_t));
  167. newTrackValues[0] = 0;
  168. char** newTrackNames = 
  169. (char**)malloc(sizeof(char*));
  170. newTrackNames[0] = stralloc("");
  171. // (re)create the menu
  172. menu = CreateOptionMenu(
  173. menu,
  174. newTrackNames, 
  175. 1,
  176. 0,
  177. GTK_SIGNAL_FUNC(on_track_menu_activate));
  178. // free up old names
  179. for (u_int8_t i = 0; i < *pNumber; i++) {
  180. free(trackNames[i]);
  181. }
  182. free(*ppValues);
  183. free(trackNames);
  184. *pIndex = 0;
  185. *pNumber = 1;
  186. *ppValues = newTrackValues;
  187. trackNames = newTrackNames;
  188. return menu;
  189. }
  190. static GtkWidget* CreateMp4TrackMenu(
  191. GtkWidget* menu,
  192. char type,
  193. char* source,
  194. u_int32_t* pIndex,
  195. u_int32_t* pNumber,
  196. u_int32_t** ppValues)
  197. {
  198. *pIndex = 0;
  199. u_int32_t newTrackNumber = 1;
  200. MP4FileHandle mp4File = MP4Read(source);
  201. char* trackType = NULL;
  202. if (mp4File) {
  203. if (type == 'V') {
  204. trackType = MP4_VIDEO_TRACK_TYPE;
  205. } else {
  206. trackType = MP4_AUDIO_TRACK_TYPE;
  207. }
  208. newTrackNumber = 
  209. MP4GetNumberOfTracks(mp4File, trackType);
  210. }
  211. u_int32_t* newTrackValues = 
  212. (u_int32_t*)malloc(sizeof(u_int32_t) * newTrackNumber);
  213. char** newTrackNames = 
  214. (char**)malloc(sizeof(char*) * newTrackNumber);
  215. if (!mp4File) {
  216. newTrackValues[0] = 0;
  217. newTrackNames[0] = stralloc("");
  218. } else {
  219. for (u_int8_t i = 0; i < newTrackNumber; i++) {
  220. MP4TrackId trackId =
  221. MP4FindTrackId(mp4File, i, trackType);
  222. char* trackName = "Unknown";
  223. char buf[64];
  224. if (trackType == MP4_VIDEO_TRACK_TYPE) {
  225. u_int8_t videoType =
  226. MP4GetTrackVideoType(mp4File, trackId);
  227. switch (videoType) {
  228. case MP4_MPEG1_VIDEO_TYPE:
  229. trackName = "MPEG1";
  230. break;
  231. case MP4_MPEG2_SIMPLE_VIDEO_TYPE:
  232. case MP4_MPEG2_MAIN_VIDEO_TYPE:
  233. case MP4_MPEG2_SNR_VIDEO_TYPE:
  234. case MP4_MPEG2_SPATIAL_VIDEO_TYPE:
  235. case MP4_MPEG2_HIGH_VIDEO_TYPE:
  236. case MP4_MPEG2_442_VIDEO_TYPE:
  237. trackName = "MPEG2";
  238. break;
  239. case MP4_MPEG4_VIDEO_TYPE:
  240. trackName = "MPEG4";
  241. break;
  242. case MP4_YUV12_VIDEO_TYPE:
  243. trackName = "YUV12";
  244. break;
  245. case MP4_H26L_VIDEO_TYPE:
  246. trackName = "H26L";
  247. break;
  248. }
  249. snprintf(buf, sizeof(buf), 
  250. "%u - %s %u x %u %.2f fps %u kbps", 
  251. trackId, 
  252. trackName,
  253. MP4GetTrackVideoWidth(mp4File, trackId),
  254. MP4GetTrackVideoHeight(mp4File, trackId),
  255. MP4GetTrackVideoFrameRate(mp4File, trackId),
  256. (MP4GetTrackBitRate(mp4File, trackId) + 500) / 1000);
  257. } else { // audio
  258. u_int8_t audioType =
  259. MP4GetTrackAudioType(mp4File, trackId);
  260. switch (audioType) {
  261. case MP4_MPEG1_AUDIO_TYPE:
  262. case MP4_MPEG2_AUDIO_TYPE:
  263. trackName = "MPEG (MP3)";
  264. break;
  265. case MP4_MPEG2_AAC_MAIN_AUDIO_TYPE:
  266. case MP4_MPEG2_AAC_LC_AUDIO_TYPE:
  267. case MP4_MPEG2_AAC_SSR_AUDIO_TYPE:
  268. case MP4_MPEG4_AUDIO_TYPE:
  269. trackName = "AAC";
  270. break;
  271. case MP4_PCM16_AUDIO_TYPE:
  272. trackName = "PCM16";
  273. break;
  274. case MP4_AC3_AUDIO_TYPE:
  275. trackName = "AC3";
  276. break;
  277. case MP4_VORBIS_AUDIO_TYPE:
  278. trackName = "Ogg Vorbis";
  279. break;
  280. }
  281. snprintf(buf, sizeof(buf), 
  282. "%u - %s %u kbps", 
  283. trackId, 
  284. trackName,
  285. (MP4GetTrackBitRate(mp4File, trackId) + 500) / 1000);
  286. }
  287. newTrackValues[i] = trackId;
  288. newTrackNames[i] = stralloc(buf);
  289. }
  290. MP4Close(mp4File);
  291. }
  292. // (re)create the menu
  293. menu = CreateOptionMenu(
  294. menu,
  295. newTrackNames, 
  296. newTrackNumber,
  297. *pIndex,
  298. GTK_SIGNAL_FUNC(on_track_menu_activate));
  299. // free up old names
  300. for (u_int8_t i = 0; i < *pNumber; i++) {
  301. free(trackNames[i]);
  302. }
  303. free(trackNames);
  304. free(*ppValues);
  305. *pNumber = newTrackNumber;
  306. trackNames = newTrackNames;
  307. *ppValues = newTrackValues;
  308. return menu;
  309. }
  310. static GtkWidget* CreateMpeg2TrackMenu(
  311. GtkWidget* menu,
  312. char type,
  313. char* source,
  314. u_int32_t* pIndex,
  315. u_int32_t* pNumber,
  316. u_int32_t** ppValues)
  317. {
  318. *pIndex = 0;
  319. u_int32_t newTrackNumber = 1;
  320. mpeg3_t* mpeg2File = mpeg3_open(source);
  321. if (mpeg2File) {
  322. if (type == 'V') {
  323. newTrackNumber = mpeg3_total_vstreams(mpeg2File);
  324. } else {
  325. newTrackNumber = mpeg3_total_astreams(mpeg2File);
  326. }
  327. }
  328. u_int32_t* newTrackValues = 
  329. (u_int32_t*)malloc(sizeof(u_int32_t) * newTrackNumber);
  330. char** newTrackNames = 
  331. (char**)malloc(sizeof(char*) * newTrackNumber);
  332. if (!mpeg2File) {
  333. newTrackValues[0] = 0;
  334. newTrackNames[0] = stralloc("");
  335. } else {
  336. for (u_int8_t i = 0; i < newTrackNumber; i++) {
  337. newTrackValues[i] = i;
  338. char buf[64];
  339. if (type == 'V') {
  340. snprintf(buf, sizeof(buf), 
  341. "%u - %u x %u @ %.2f fps", 
  342. i + 1,
  343. mpeg3_video_width(mpeg2File, i),
  344. mpeg3_video_height(mpeg2File, i),
  345. mpeg3_frame_rate(mpeg2File, i));
  346. } else {
  347. char* afmt =
  348. mpeg3_audio_format(mpeg2File, i);
  349. // use more familar though less accurate name
  350. if (!strcasecmp(afmt, "MPEG")) {
  351. afmt = "MP3";
  352. }
  353. snprintf(buf, sizeof(buf), 
  354. "%u - %s  %u channels @ %u Hz", 
  355. i + 1,
  356. afmt,
  357. mpeg3_audio_channels(mpeg2File, i),
  358. mpeg3_sample_rate(mpeg2File, i));
  359. }
  360. newTrackNames[i] = stralloc(buf);
  361. }
  362. mpeg3_close(mpeg2File);
  363. }
  364. // (re)create the menu
  365. menu = CreateOptionMenu(
  366. menu,
  367. newTrackNames, 
  368. newTrackNumber,
  369. *pIndex,
  370. GTK_SIGNAL_FUNC(on_track_menu_activate));
  371. // free up old names
  372. for (u_int8_t i = 0; i < *pNumber; i++) {
  373. free(trackNames[i]);
  374. }
  375. free(trackNames);
  376. free(*ppValues);
  377. *pNumber = newTrackNumber;
  378. trackNames = newTrackNames;
  379. *ppValues = newTrackValues;
  380. return menu;
  381. }
  382. GtkWidget* CreateTrackMenu(
  383. GtkWidget* menu,
  384. char type, 
  385. char* source,
  386. u_int32_t* pMenuIndex,
  387. u_int32_t* pMenuNumber,
  388. u_int32_t** ppMenuValues)
  389. {
  390. pTrackIndex = pMenuIndex;
  391. if (IsMp4File(source)) {
  392. return CreateMp4TrackMenu(
  393. menu, type, source, pMenuIndex, pMenuNumber, ppMenuValues);
  394. } else if (IsMpeg2File(source)) {
  395. return CreateMpeg2TrackMenu(
  396. menu, type, source, pMenuIndex, pMenuNumber, ppMenuValues);
  397. } else {
  398. return CreateNullTrackMenu(
  399. menu, type, source, pMenuIndex, pMenuNumber, ppMenuValues);
  400. }
  401. }