Форум программистов, компьютерный форум, киберфорум
Наши страницы
Программирование Android
Войти
Регистрация
Восстановить пароль
 
Max_92
25 / 7 / 1
Регистрация: 26.04.2010
Сообщений: 205
1

Как достичь приемлемого качества фото и видео, используя CameraAPI

05.12.2014, 13:41. Просмотров 401. Ответов 0
Метки нет (Все метки)

Вот уже несколько месяцев как разрабатываю библиотеку для работы с камерой, используя средства, имеющиеся в SDK (19-ом). Суть в том, что реально устройство, например, может писать видео с разрешением 720x480 (так пишет стандратная камера с высокими настройками кач-ва) и с достаточно высоким битрейтом, в то время как в моём коде, используя стандартный гугловский MediaRecorder (http://developer.android.com/referen...aRecorder.html) я такого качества добиться не могу.

Во-первых: для открытой фронтальной камеры список
Java
1
camera.getParameters().getSupportedVideoSizes();
не содержит того самого макс. разрешения,
во-вторых перед prepare() рекордера я пытаюсь выставить профиль 480P, предварительно проверив, что для камеры с таким id он действительно поддерживается:

Java
1
2
3
4
5
6
7
        if (videoSettings.quality != QUALITY.DEFAULT) {
            if (!CamcorderProfile.hasProfile(cameraId, videoSettings.quality.getValue())) {
                logger.error("profile " + videoSettings.quality.getValue() + " is not suppoted for camera with id " + cameraId
                        + ", changing to DEFAULT...");
                videoSettings.quality = QUALITY.DEFAULT;
            }
        }
после чего либо выставляю этот профиль, ловя RuntimeException, либо выставляю отдельные параметры, при том в нужном порядке (set sources -> setOutputFormat -> setVideoSize -> setVideoFrameRate -> set encoders):

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
                    if (videoSettings.quality != QUALITY.DEFAULT) {
 
            logger.debug("setting profile " + videoSettings.quality.getValue() + "...");
            try {
 
                mediaRecorder.setProfile(CamcorderProfile.get(videoSettings.quality.getValue(), cameraId));
            } catch (RuntimeException e) {
                logger.error("a RuntimeException occured during setProfile() : " + e.getMessage());
 
                videoSettings.quality = QUALITY.DEFAULT;
 
                return false;
            }
 
            logger.debug("quality=" + videoSettings.quality);
 
        } else {
 
            logger.debug("setting single parameters...");
 
            setOutputFormatByEncoder(videoSettings.videoEncoder);
            logger.debug("videoEncoder=" + videoSettings.videoEncoder);
 
            if (videoSettings.width > 0 && videoSettings.height > 0) {
                mediaRecorder.setVideoSize(videoSettings.width, videoSettings.height);
                logger.debug("videoSize: width=" + videoSettings.width + ", height=" + videoSettings.height);
            } else {
                logger.error("wrong video size: " + videoSettings.width + " x " + videoSettings.height);
            }
 
            // if bitrate value is more than max acceptable bitrate, bitrate in video file will be max and constant
            // mediaRecorder.setVideoEncodingBitRate(256000);
 
            if (videoSettings.frameRate > 0 && videoSettings.frameRate <= VideoSettings.FRAME_RATE_MAX) {
                mediaRecorder.setVideoFrameRate(videoSettings.frameRate);
                logger.debug("frameRate=" + videoSettings.frameRate);
            }
 
            mediaRecorder.setAudioEncoder(videoSettings.audioEncoder.getValue());
            logger.debug("audioEncoder=" + videoSettings.audioEncoder);
 
            mediaRecorder.setVideoEncoder(videoSettings.videoEncoder.getValue());
            logger.debug("videoEncoder=" + videoSettings.videoEncoder);
        }
смысл в том, что на выставлении профиля 480P этот exception бросается всегда, а если брать профиль HIGH, который по заверениям должен быть на всех девайсах, то разрешение выставляется самое низкое для этого телефона (176x144) и все настройки дефолтные.
вручную я параметры выставляю, если был выбран профиль DEFAULT. битрейт видео, к слову, так же нельзя выставить выше 256 kbit/s
таким образом, макс. разрешение видео у меня 480x320 и битрейт 256.

Качество фоток так же посредственное, но там ситуация несколько лучше, по крайней мере в колбеке onPictureTaken() я могу получить фотку с разрешением порядка 1600 пикселей.

Текущие параметры камеры непосредственно перед взятием фотки, например, выставляю таким образом:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    public boolean setCameraPhotoParams(PhotoSettings photoSettings) {
        logger.debug("setCameraPhotoParams()");
 
        if (camera == null) {
            logger.error("camera is null");
            return false;
        }
 
        if (photoSettings == null) {
            logger.error("photoSettings is null");
            return false;
        }
 
        if (isMediaRecorderRecording) {
            logger.error("can't set parameters: media recorder is now recording");
            return false;
        }
 
        final Parameters params;
        try {
            params = camera.getParameters();
        } catch (RuntimeException e) {
            logger.error("a RuntimeException occured during getParameters(): " + e.getMessage());
            return false;
        }
 
        boolean isPreviewSizeSupported = false;
 
        final List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
 
        if ((photoSettings.previewWidth > 0) && (photoSettings.previewHeight > 0)) {
 
            if (supportedPreviewSizes != null && supportedPreviewSizes.size() != 0) {
                for (int i = 0; i < supportedPreviewSizes.size(); i++) {
 
                    // logger.debug(" _ preview " + supportedPreviewSizes.get(i).width + " and height " +
                    // supportedPreviewSizes.get(i).height);
 
                    if ((supportedPreviewSizes.get(i).width == photoSettings.previewWidth)
                            && (supportedPreviewSizes.get(i).height == photoSettings.previewHeight)) {
                        logger.debug("PREVIEW width " + photoSettings.previewWidth + " and height " + photoSettings.previewHeight
                                + " is supported");
                        params.setPreviewSize(photoSettings.previewWidth, photoSettings.previewHeight);
                        isPreviewSizeSupported = true;
                        break;
                    }
                }
            } else {
                logger.error("no supported preview sizes for this camera");
            }
        }
 
        if (!isPreviewSizeSupported) {
            logger.error("PREVIEW width " + photoSettings.previewWidth + " and height " + photoSettings.previewHeight + " is NOT supported");
 
            final Camera.Size optimalPreviewSize = getOptimalPreviewSize(getSupportedPictureSizes(), surfaceWidth, surfaceHeight);
            // final Camera.Size highPreviewSize = findHighSize(getSupportedPreviewSizes());
 
            photoSettings.previewWidth = optimalPreviewSize.width;
            photoSettings.previewHeight = optimalPreviewSize.height;
            params.setPreviewSize(photoSettings.previewWidth, photoSettings.previewHeight);
        }
 
        boolean isPictureSizeSupported = false;
 
        final List<Camera.Size> supportedPictureSizes = params.getSupportedPictureSizes();
 
        if ((photoSettings.pictureWidth > 0) && (photoSettings.pictureHeight > 0)) {
 
            if (supportedPictureSizes != null && supportedPictureSizes.size() != 0) {
                for (int i = 0; i < supportedPictureSizes.size(); i++) {
 
                    // logger.debug(" _ preview " + supportedPictureSizes.get(i).width + " and height " +
                    // supportedPictureSizes.get(i).height);
 
                    if ((supportedPictureSizes.get(i).width == photoSettings.pictureWidth)
                            && (supportedPictureSizes.get(i).height == photoSettings.pictureHeight)) {
                        logger.debug("PICTURE width " + photoSettings.pictureWidth + " and height " + photoSettings.pictureHeight
                                + " is supported");
                        params.setPictureSize(photoSettings.pictureWidth, photoSettings.pictureHeight);
                        isPictureSizeSupported = true;
                        break;
                    }
                }
            } else {
                logger.error("no supported pictures sizes for this camera");
            }
        }
 
        if (!isPictureSizeSupported) {
            logger.error("PICTURE width " + photoSettings.pictureWidth + " and height " + photoSettings.pictureHeight + " is NOT supported");
            photoSettings.pictureWidth = params.getPictureSize().width;
            photoSettings.pictureHeight = params.getPictureSize().height;
            // params.setPictureSize(photoSettings.pictureWidth, photoSettings.pictureHeight);
        }
 
        final List<Integer> supportedPreviewFormats = params.getSupportedPreviewFormats();
        if (supportedPreviewFormats != null && supportedPreviewFormats.size() != 0) {
            for (int i = 0; i < supportedPreviewFormats.size(); i++) {
                if (IMAGE_FORMAT.fromNativeValue(supportedPreviewFormats.get(i)) == photoSettings.previewFormat) {
                    logger.debug("PREVIEW FORMAT: " + photoSettings.previewFormat + " is supported");
                    params.setPreviewFormat(photoSettings.previewFormat.getValue());
                    break;
                }
            }
        } else {
            logger.error("no supported preview formats for this camera");
        }
 
        final List<Integer> supportedPictureFormats = params.getSupportedPictureFormats();
        if (supportedPictureFormats != null && supportedPictureFormats.size() != 0) {
            for (int i = 0; i < supportedPictureFormats.size(); i++) {
                if (IMAGE_FORMAT.fromNativeValue(supportedPictureFormats.get(i)) == photoSettings.pictureFormat) {
                    logger.debug("PICTURE FORMAT: " + photoSettings.pictureFormat + " is supported");
                    params.setPictureFormat(photoSettings.pictureFormat.getValue());
                    break;
                }
            }
        } else {
            logger.error("no supported picture formats for this camera");
        }
 
        if ((photoSettings.jpegQuality > 0) && (photoSettings.jpegQuality <= 100)) {
            logger.debug("jpegQuality=" + photoSettings.jpegQuality);
            params.setJpegQuality(photoSettings.jpegQuality);
            params.setJpegThumbnailQuality(photoSettings.jpegQuality);
        }
 
        final List<String> supportedFlashModes = params.getSupportedFlashModes();
        if (supportedFlashModes != null && supportedFlashModes.size() != 0) {
            for (int i = 0; i < supportedFlashModes.size(); i++) {
                if (supportedFlashModes.get(i).equals(photoSettings.flashMode)) {
                    logger.debug("FLASH MODE: " + photoSettings.flashMode + " is supported");
                    params.setFlashMode(photoSettings.flashMode.getValue());
                    break;
                }
            }
        } else {
            logger.error("no supported flash modes for this camera");
        }
 
        setCameraFocus(photoSettings.focusMode);
        setCameraColorEffect(photoSettings.colorEffect);
 
        camera.setParameters(params);
        return true;
    }
В общем, кто сталкивался подобным? Как можно достичь приемлемого кач-ва?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.12.2014, 13:41
Ответы с готовыми решениями:

Отправка фото в инстаграм используя апи
Всем привет, пару лет назад, задавался таким вопросов, но ответ был один,...

Выбор обфускатора: сочетание бесплатности и приемлемого качества
Понимаю что много таких тем есть ,но ничего в них не могу понять какой...

Как загрузить фото на хостинг без потери качества при уменьшении изображения?
Как партнерки и другие сайты загружают фото, Баннеры и тизеры на свой хостинг с...

Как заменить звук FLV(mp4) без потери качества видео
Доброго времени суток! Имеется видео формат FLV потому как было скачано с ютуба...

Улучшение качества фото
Здравствуйте, подскажите, пожалуйста, можно ли улучшить качество фото, чтобы...

0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.12.2014, 13:41

Компьютер виснет при просмотре онлайн видео, видео HD качества и при сильной нагрузке.
Здравствуйте, У меня такая проблема: Комп виснит при просмотре онлайн...

Как создать фото\видео альбом
Здравствуйте. Как создать такое меню на главной странице, чтобы был заголовок...

Нужно как-то достать фото и видео из IPad
Не знаю что и делать, надеюсь кто-то сможет помочь!!! Ситуация такая: обновил...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru