xref: /haiku/src/apps/mediaconverter/MediaFileInfo.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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 <stdio.h>
13 
14 #undef B_TRANSLATION_CONTEXT
15 #define B_TRANSLATION_CONTEXT "MediaFileInfo"
16 
17 MediaFileInfo::MediaFileInfo(BMediaFile* file)
18 {
19 	LoadInfo(file);
20 }
21 
22 
23 status_t
24 MediaFileInfo::LoadInfo(BMediaFile* file)
25 {
26 	_Reset();
27 	if (!file)
28 		return B_BAD_VALUE;
29 
30 	BMediaTrack* track;
31 	media_format format;
32 	memset(&format, 0, sizeof(format));
33 	media_codec_info codecInfo;
34 	bool audioDone(false), videoDone(false);
35 	bigtime_t audioDuration = 0;
36 	bigtime_t videoDuration = 0;
37 	int32 tracks = file->CountTracks();
38 	int64 videoFrames = 0;
39 	int64 audioFrames = 0;
40 	status_t ret = B_OK;
41 
42 	for (int32 i = 0; i < tracks && (!audioDone || !videoDone); i++) {
43 		track = file->TrackAt(i);
44 		if (track == NULL)
45 			return B_ERROR;
46 
47 		ret = track->InitCheck();
48 		if (ret != B_OK)
49 			return ret;
50 
51 		ret = track->EncodedFormat(&format);
52 		if (ret != B_OK)
53 			return ret;
54 
55 		if (format.IsVideo()) {
56 			memset(&format, 0, sizeof(format));
57 			format.type = B_MEDIA_RAW_VIDEO;
58 
59 			ret = track->DecodedFormat(&format);
60 			if (ret != B_OK)
61 				return ret;
62 
63 			media_raw_video_format *rvf = &(format.u.raw_video);
64 
65 			ret = track->GetCodecInfo(&codecInfo);
66 			if (ret != B_OK)
67 				return ret;
68 
69 			video.format << codecInfo.pretty_name;
70 			videoDuration = track->Duration();
71 			videoFrames = track->CountFrames();
72 
73 			BString details;
74 			snprintf(details.LockBuffer(256), 256,
75 					B_TRANSLATE_COMMENT("%u x %u, %.2ffps / %Ld frames",
76 					"Width x Height, fps / frames"),
77 					format.Width(), format.Height(),
78 					rvf->field_rate / rvf->interlace, videoFrames);
79 			details.UnlockBuffer();
80 			video.details << details;
81 			videoDone = true;
82 
83 		} else if (format.IsAudio()) {
84 			memset(&format, 0, sizeof(format));
85 			format.type = B_MEDIA_RAW_AUDIO;
86 			ret = track->DecodedFormat(&format);
87 			if (ret != B_OK)
88 				return ret;
89 			media_raw_audio_format *raf = &(format.u.raw_audio);
90 			char bytesPerSample = (char)(raf->format & 0xf);
91 
92 			BString details;
93 			if (bytesPerSample == 1 || bytesPerSample == 2) {
94 				snprintf(details.LockBuffer(16), 16,
95 						B_TRANSLATE("%d bit "), bytesPerSample * 8);
96 			} else {
97 				snprintf(details.LockBuffer(16), 16,
98 						B_TRANSLATE("%d byte "), bytesPerSample);
99 			}
100 			details.UnlockBuffer();
101 			audio.details << details;
102 
103 			ret = track->GetCodecInfo(&codecInfo);
104 			if (ret != B_OK)
105 				return ret;
106 
107 			audio.format << codecInfo.pretty_name;
108 			audioDuration = track->Duration();
109 			audioFrames = track->CountFrames();
110 			BString channels;
111 			if (raf->channel_count == 1) {
112 				snprintf(channels.LockBuffer(64), 64,
113 				B_TRANSLATE("%.1f kHz mono / %lld frames"),
114 				raf->frame_rate / 1000.f, audioFrames);
115 			} else if (raf->channel_count == 2) {
116 				snprintf(channels.LockBuffer(64), 64,
117 				B_TRANSLATE("%.1f kHz stereo / %lld frames"),
118 				raf->frame_rate / 1000.f, audioFrames);
119 			} else {
120 				snprintf(channels.LockBuffer(64), 64,
121 				B_TRANSLATE("%.1f kHz %ld channel / %lld frames"),
122 				raf->frame_rate / 1000.f, raf->channel_count, audioFrames);
123 			}
124 			channels.UnlockBuffer();
125 			audio.details << channels;
126 
127 			audioDone = true;
128 		}
129 		ret = file->ReleaseTrack(track);
130 		if (ret != B_OK)
131 			return ret;
132 	}
133 
134 	useconds = MAX(audioDuration, videoDuration);
135 	duration << (int32)(useconds / 1000000)
136 			  << B_TRANSLATE(" seconds");
137 
138 	return B_OK;
139 }
140 
141 
142 void
143 MediaFileInfo::_Reset()
144 {
145 	audio.details.SetTo("");
146 	audio.format.SetTo("");
147 	video.details.SetTo("");
148 	video.format.SetTo("");
149 	useconds = 0;
150 	duration.SetTo("");
151 }
152