xref: /haiku/src/apps/mediaconverter/MediaFileInfo.cpp (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
1 // Copyright 1999, Be Incorporated. All Rights Reserved.
2 // Copyright 2000-2004, Jun Suzuki. All Rights Reserved.
3 // Copyright 2007, Stephan Aßmus. All Rights Reserved.
4 // Copyright 2010, Haiku, Inc. All Rights Reserved.
5 // This file may be used under the terms of the Be Sample Code License.
6 
7 
8 #include "MediaFileInfo.h"
9 
10 #include <Catalog.h>
11 #include <MediaTrack.h>
12 #include <MessageFormat.h>
13 #include <stdio.h>
14 
15 #undef B_TRANSLATION_CONTEXT
16 #define B_TRANSLATION_CONTEXT "MediaFileInfo"
17 
18 MediaFileInfo::MediaFileInfo(BMediaFile* file)
19 {
20 	LoadInfo(file);
21 }
22 
23 
24 status_t
25 MediaFileInfo::LoadInfo(BMediaFile* file)
26 {
27 	_Reset();
28 	if (!file)
29 		return B_BAD_VALUE;
30 
31 	BMediaTrack* track;
32 	media_format format;
33 	memset(&format, 0, sizeof(format));
34 	media_codec_info codecInfo;
35 	bool audioDone(false), videoDone(false);
36 	bigtime_t audioDuration = 0;
37 	bigtime_t videoDuration = 0;
38 	int32 tracks = file->CountTracks();
39 	int64 videoFrames = 0;
40 	int64 audioFrames = 0;
41 	status_t ret = B_OK;
42 
43 	for (int32 i = 0; i < tracks && (!audioDone || !videoDone); i++) {
44 		track = file->TrackAt(i);
45 		if (track == NULL)
46 			return B_ERROR;
47 
48 		ret = track->InitCheck();
49 		if (ret != B_OK)
50 			return ret;
51 
52 		ret = track->EncodedFormat(&format);
53 		if (ret != B_OK)
54 			return ret;
55 
56 		static BMessageFormat frameFormat(B_TRANSLATE(
57 			"{0, plural, one{# frame} other{# frames}}"));
58 
59 		if (format.IsVideo()) {
60 			memset(&format, 0, sizeof(format));
61 			format.type = B_MEDIA_RAW_VIDEO;
62 
63 			ret = track->DecodedFormat(&format);
64 			if (ret != B_OK)
65 				return ret;
66 
67 			media_raw_video_format *rvf = &(format.u.raw_video);
68 
69 			ret = track->GetCodecInfo(&codecInfo);
70 			if (ret != B_OK)
71 				return ret;
72 
73 			video.format << codecInfo.pretty_name;
74 			videoDuration = track->Duration();
75 			videoFrames = track->CountFrames();
76 
77 			BString details;
78 			details.SetToFormat(
79 				B_TRANSLATE_COMMENT("%u x %u, %.2ffps", "Width x Height, fps"),
80 				format.Width(), format.Height(),
81 				rvf->field_rate / rvf->interlace);
82 
83 			details << " / ";
84 			frameFormat.Format(details, videoFrames);
85 
86 			video.details << details;
87 			videoDone = true;
88 
89 		} else if (format.IsAudio()) {
90 			memset(&format, 0, sizeof(format));
91 			format.type = B_MEDIA_RAW_AUDIO;
92 			ret = track->DecodedFormat(&format);
93 			if (ret != B_OK)
94 				return ret;
95 			media_raw_audio_format *raf = &(format.u.raw_audio);
96 			char bytesPerSample = (char)(raf->format & 0xf);
97 
98 			BString details;
99 			if (bytesPerSample == 1 || bytesPerSample == 2) {
100 				static BMessageFormat bitFormat(
101 					B_TRANSLATE("{0, plural, one{# bit} other{# bits}}"));
102 				bitFormat.Format(details, bytesPerSample * 8);
103 				details.SetToFormat(B_TRANSLATE("%d bit "), bytesPerSample * 8);
104 			} else {
105 				static BMessageFormat bitFormat(
106 					B_TRANSLATE("{0, plural, one{# byte} other{# bytes}}"));
107 				bitFormat.Format(details, bytesPerSample);
108 			}
109 			audio.details << details;
110 			audio.details << " ";
111 
112 			ret = track->GetCodecInfo(&codecInfo);
113 			if (ret != B_OK)
114 				return ret;
115 
116 			audio.format << codecInfo.pretty_name;
117 			audioDuration = track->Duration();
118 			audioFrames = track->CountFrames();
119 			BString channels;
120 			if (raf->channel_count == 1) {
121 				channels.SetToFormat(B_TRANSLATE("%.1f kHz mono"),
122 					raf->frame_rate / 1000.f);
123 			} else if (raf->channel_count == 2) {
124 				channels.SetToFormat(B_TRANSLATE("%.1f kHz stereo"),
125 					raf->frame_rate / 1000.f);
126 			} else {
127 				channels.SetToFormat(B_TRANSLATE("%.1f kHz %ld channel"),
128 					raf->frame_rate / 1000.f, raf->channel_count);
129 			}
130 
131 			channels << " / ";
132 			frameFormat.Format(channels, audioFrames);
133 
134 			audio.details << channels;
135 
136 			audioDone = true;
137 		}
138 		ret = file->ReleaseTrack(track);
139 		if (ret != B_OK)
140 			return ret;
141 	}
142 
143 	useconds = MAX(audioDuration, videoDuration);
144 	duration << (int32)(useconds / 1000000)
145 			<< B_TRANSLATE(" seconds");
146 
147 	return B_OK;
148 }
149 
150 
151 void
152 MediaFileInfo::_Reset()
153 {
154 	audio.details.SetTo("");
155 	audio.format.SetTo("");
156 	video.details.SetTo("");
157 	video.format.SetTo("");
158 	useconds = 0;
159 	duration.SetTo("");
160 }
161