1/*
2 * Copyright 2008, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * 		Alexandre Deckner <alex@zappotek.com>
7 */
8
9#include "VideoFileTexture.h"
10
11#include <Bitmap.h>
12#include <Entry.h>
13#include <MediaFile.h>
14#include <MediaTrack.h>
15
16#include <GL/gl.h>
17#include <GL/glu.h>
18#include <string.h>
19#include <stdio.h>
20
21
22VideoFileTexture::VideoFileTexture(const char* fileName)
23	:
24	Texture(),
25	fMediaFile(NULL),
26	fVideoTrack(NULL),
27	fVideoBitmap(NULL)
28{
29	_Load(fileName);
30}
31
32
33VideoFileTexture::~VideoFileTexture()
34{
35	delete fVideoBitmap;
36
37	if (fMediaFile != NULL) {
38		fMediaFile->ReleaseAllTracks();
39		fMediaFile->CloseFile();
40		delete fMediaFile;
41	}
42}
43
44
45void
46VideoFileTexture::_Load(const char* fileName)
47{
48	BEntry entry(fileName);
49	entry_ref ref;
50	entry.GetRef(&ref);
51
52	fMediaFile = new BMediaFile(&ref);
53	status_t err = fMediaFile->InitCheck();
54	if (err != B_OK) {
55		printf("cannot contruct BMediaFile object -- %s\n", strerror(err));
56		return;
57	}
58
59	int32 trackCount = fMediaFile->CountTracks();
60
61	for (int32 i = 0; i < trackCount; i++) {
62		BMediaTrack* track = fMediaFile->TrackAt(i);
63		if (track == NULL) {
64			printf("cannot contruct BMediaTrack object\n");
65			return;
66		}
67
68		// get the encoded format
69		media_format format;
70		err = track->EncodedFormat(&format);
71		if (err != B_OK) {
72			printf("BMediaTrack::EncodedFormat error -- %s\n", strerror(err));
73			return;
74		}
75
76		if (format.type == B_MEDIA_ENCODED_VIDEO) {
77			fVideoTrack = track;
78			// allocate a bitmap large enough to contain the decoded frame.
79			BRect bounds(0.0, 0.0,
80				format.u.encoded_video.output.display.line_width - 1.0,
81				format.u.encoded_video.output.display.line_count - 1.0);
82			fVideoBitmap = new BBitmap(bounds, B_RGB32);
83
84			// specifiy the decoded format. we derive this information from
85			// the encoded format.
86			format = media_format();
87			format.u.raw_video.last_active = (int32) (bounds.Height() - 1.0);
88			format.u.raw_video.orientation = B_VIDEO_TOP_LEFT_RIGHT;
89			format.u.raw_video.pixel_width_aspect = 1;
90			format.u.raw_video.pixel_height_aspect = 3;
91			format.u.raw_video.display.format = fVideoBitmap->ColorSpace();
92			format.u.raw_video.display.line_width = (int32) bounds.Width();
93			format.u.raw_video.display.line_count = (int32) bounds.Height();
94			format.u.raw_video.display.bytes_per_row
95				= fVideoBitmap->BytesPerRow();
96
97			err = fVideoTrack->DecodedFormat(&format);
98			if (err != B_OK) {
99				printf("error with BMediaTrack::DecodedFormat() -- %s\n",
100					strerror(err));
101				return;
102			}
103
104			// Create Texture
105			glGenTextures(1, &fId);
106			glBindTexture(GL_TEXTURE_2D, fId);
107			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
108			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
109			glTexImage2D(GL_TEXTURE_2D, 0, 4,
110				(int) fVideoBitmap->Bounds().Width() + 1,
111				(int) fVideoBitmap->Bounds().Height() + 1,
112				0, GL_BGRA, GL_UNSIGNED_BYTE, fVideoBitmap->Bits());
113		}
114	}
115}
116
117
118void
119VideoFileTexture::Update(float /*dt*/) {
120	// TODO loop
121	int64 frameCount = 0;
122	media_header mh;
123	status_t err
124		= fVideoTrack->ReadFrames(fVideoBitmap->Bits(), &frameCount, &mh);
125	if (err) {
126		printf("BMediaTrack::ReadFrames error -- %s\n", strerror(err));
127		return;
128	}
129
130	glBindTexture(GL_TEXTURE_2D, fId);
131	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
132		(int)fVideoBitmap->Bounds().Width() + 1,
133		(int)fVideoBitmap->Bounds().Height() + 1,
134		GL_BGRA, GL_UNSIGNED_BYTE, fVideoBitmap->Bits());
135}
136
137