Форум программистов, компьютерный форум CyberForum.ru

Программирование Android

Войти
Регистрация
Восстановить пароль
 
Max_92
25 / 7 / 2
Регистрация: 26.04.2010
Сообщений: 205
#1

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

05.12.2014, 13:41. Просмотров 334. Ответов 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;
    }
В общем, кто сталкивался подобным? Как можно достичь приемлемого кач-ва?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.12.2014, 13:41     Как достичь приемлемого качества фото и видео, используя CameraAPI
Посмотрите здесь:

Как можно воспроизвести видео Android
Android Нужна идея. Как научить офиц. приложение Instagram, автоматически, например, комментить фото
Проверка качества соединения с сайтом Android
Как воспроизвести потоковое видео, можно ли? Basic4Android
Как Instagram обрезает фото? Android
Android Как создать всплывающее окно с фото
Как добавить ютуб видео в приложение Android
Как встроить видео Android
Android Как указать стандартным галере или фото путь поиска картинок
Android Как слушать видео не выводя видео на экран
Отправка фото в инстаграм используя апи Android
Android Как правильно прочитать все фото которые есть в галерее

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать тему
Опции темы

Текущее время: 13:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru